grthtrhthjhtyjytjytkergtrhtrjytjerhrfh4:24 29/09/2026a Û1j‡rã@sÖddlZddlZddlZddlZddlZddlZddlZddlZddlmZddl m Z ddl m Z ddl mZz ddlZWneyŽYn0dZdZdZd Zd ZGd d „d ƒZGd d„deƒZGdd„deƒZdS)éN)Údatetime)ÚLock)Ú find_spec)Úsos_get_command_outputÚfileÚlinkZnodeÚdirz contaner filec@sÈeZdZdZedd„ƒZe d¡ZdZ dZ e ƒZ dd„Z d d „Zd d „Zd d„Zdd„Zdd„Zdd„Zd-dd„Zd.dd„Zdd„Zdd„Zdd „Zd!d"„Zd#d$„Zd%d&„Zd'd(„Zd)d*„Zd+d,„ZdS)/ÚArchivez!Abstract base class for archives.cCs|jS)z6Returns the archive class's name as a string. )Ú__name__)Úcls©r ú//usr/lib/python3.9/site-packages/sos/archive.pyÚ archive_type,szArchive.archive_typeZsosZunsetFcCsd| ¡›d|›�S)Nz [archive:z] )r©ÚselfÚmsgr r r Ú _format_msg9szArchive._format_msgcCs ||_dS©N)Ú_debug)rÚdebugr r r Ú set_debug<szArchive.set_debugcCs|j | |¡¡dSr)ÚlogÚerrorrrr r r Ú log_error?szArchive.log_errorcCs|j | |¡¡dSr)rZwarningrrr r r Úlog_warnBszArchive.log_warncCs|j | |¡¡dSr)rÚinforrr r r Úlog_infoEszArchive.log_infocCs |js dS|j | |¡¡dSr)rrrrrr r r Ú log_debugHszArchive.log_debugcCs|jSr)Ú_name©rr r r ÚnameMsz Archive.nameNcCst‚dSr©ÚNotImplementedError)rÚsrcÚdestÚforcer r r Úadd_fileSszArchive.add_fileÚwcCst‚dSrr!)rÚcontentr$Úmoder r r Ú add_stringVszArchive.add_stringcCst‚dSrr!)rr(r$r r r Ú add_binaryYszArchive.add_binarycCst‚dSrr!)rÚsourceÚ link_namer r r Úadd_link\szArchive.add_linkcCst‚dSrr!©rÚpathr r r Úadd_dir_szArchive.add_dircCst‚dSrr!)rr0r)Údevicer r r Úadd_nodebszArchive.add_nodecCst‚dS)z´Return a temporary directory that clients of the archive may use to write content to. The content of the path is guaranteed to be included in the generated archive.Nr!rr r r Ú get_tmp_direszArchive.get_tmp_dircCst‚dS)zºReturn the maximum file name length this archive can support. This is the lesser of the name length limit of the archive format and any temporary file system based cache.Nr!rr r r Úname_maxkszArchive.name_maxcCst‚dS)aTReturn a string representing the path to the temporary archive. For archive classes that implement in-line handling this will be the archive file itself. Archives that use a directory based cache prior to packaging should return the path to the temporary directory where the report content is locatedNr!rr r r Úget_archive_pathqszArchive.get_archive_pathcCst‚dS)z:Clean up any temporary resources used by an Archive class.Nr!rr r r ÚcleanupzszArchive.cleanupcCst‚dS)aFinalize an archive object via method. This may involve creating An archive that is subsequently compressed or simply closing an archive that supports in-line handling. If method is automatic then the following methods are tried in order: xz, gzipNr!©rÚmethodr r r Úfinalize~szArchive.finalize)NF)r')r Ú __module__Ú __qualname__Ú__doc__Ú classmethodrÚloggingZ getLoggerrrrrÚ _path_lockrrrrrrr r&r*r+r.r1r3r4r5r6r7r:r r r r r )s2     r c@sèeZdZdZdZdZdZd7dd„Zdd„Zdd „Z d8d d „Z d9dd„Z dd„Z d:dd„Z d;dd„Zdd„Zdd„Zdd„Zdd„Zdd „Zd!d"„Zd#d$„ZdTest whether path ``path`` is inside the archive. rB)rXrFr0rM)r0©Úrootr r Ú in_archiveÆsz8FileCacheArchive._make_leading_paths..in_archiverCr)rCrBz Making path ©r)zMaking symlink 'ú' -> 'rEzMaking directory )rrNrXrFr0ÚisdirrYÚsplitÚappendÚreverserMÚexistsÚislinkÚreadlinkÚ_make_leading_pathsÚnormpathrSrHÚsymlinkÚmkdir)rr#r)r$r\Úsrc_dirr0Z path_compsÚheadÚtailZabs_pathZsrc_pathÚcompÚtargetZ target_dirZ target_srcr rZr rf¬sR  ÿ      ÿ  z$FileCacheArchive._make_leading_pathsFc Cs\|p | |¡}|tkr|}ntj |¡d}|s4|Stj |¡r\tj |¡s\td|›d�ƒ‚tj |¡sŽ|tkrt|ntj |¡d}| |¡dd„}|rž|Stj |¡�rXt  |¡}d} |t krÞt   |j ¡sÞt| |dfƒ‚|tk�rt  |j ¡�st| |dfƒ‚|tk�r,||j ƒ�s,t| |d fƒ‚|tk�rTt  |j ¡�sTt| |d fƒ‚d S|S) a4Check a new destination path in the archive. Since it is possible for multiple plugins to collect the same paths, and since plugins can now run concurrently, it is possible for two threads to race in archive methods: historically the archive class only needed to test for the actual presence of a path, since it was impossible for another `Archive` client to enter the class while another method invocation was being dispatched. Deal with this by implementing a locking scheme for operations that modify the path structure of the archive, and by testing explicitly for conflicts with any existing content at the specified destination path. It is not an error to attempt to create a path that already exists in the archive so long as the type of the object to be added matches the type of object already found at the path. It is an error to attempt to re-create an existing path with a different path type (for example, creating a symbolic link at a path already occupied by a regular file). :param src: the source path to be copied to the archive :param path_type: the type of object to be copied :param dest: an optional destination path :param force: force file creation even if the path exists :returns: An absolute destination path if the path should be copied now or `None` otherwise rzpath 'z' exists and is not a directorycSs(tt |¡t |¡t |¡t |¡gƒSr)ÚanyÚstatÚS_ISBLKÚS_ISCHRÚS_ISFIFOÚS_ISSOCKr]r r r Ú is_special8s üz/FileCacheArchive.check_path..is_specialz path '%s' exists and is not a %sz regular filez symbolic linkz special fileZ directoryN)rVÚP_DIRrFr0r`rcr_Ú ValueErrorrfÚlstatÚP_FILErpÚS_ISREGÚst_modeÚP_LINKÚS_ISLNKÚP_NODEÚS_ISDIR) rr#Ú path_typer$r%Údest_dirrjruÚstZve_msgr r r Ú check_path s6   zFileCacheArchive.check_pathc Cs¦zdt |¡}| d¡s | d¡rDt ||¡tj||j|jfd�n t ||¡t  ||j |j ¡Wn<t y }z$|  d|›d|›d�¡WYd}~n d}~00dS)Nú/sys/ú/proc/)Únszcaught 'z' setting attributes of 'rE)rFrprXÚshutilÚcopymodeÚutimeÚ st_atime_nsÚ st_mtime_nsÚcopystatÚchownÚst_uidÚst_gidÚ Exceptionr)rr#r$Ú_statÚer r r Ú_copy_attributesTs   z!FileCacheArchive._copy_attributesc CsP|j��2|s|}|j|t|d�}|s6WdƒdSt|ddƒsÀzt ||¡WnRty¤}z:| d¡s�| d¡rxn| d|›d|›d�¡WYd}~n d}~00|  ||¡d|›d�}nR|  d¡t |d d d ��$}|D]}|  |¡qÞWdƒn1�s0Yd }|  d |›d|j›d�¡Wdƒn1�sB0YdS)N©r%Úreadr„r…zFile z not collected: 'rErr'úutf-8©Úencodingz open filezadded z to FileCacheArchive ')r@rƒryÚgetattrr‡ÚcopyÚOSErrorrXrr“ÚseekÚopenÚwriterrN)rr#r$r%r’Ú file_nameÚfÚliner r r r&as.  .  , ÿzFileCacheArchive.add_filer'c CsÀ|j�¦|}|j|tdd�}tj||dd��b}t|tƒrD| dd¡}| |¡t j   |¡rf|  ||¡|  d|›d|j›d �¡Wdƒn1s”0YWdƒn1s²0YdS) NTr”r–r—Úutf8Úignorezadded string at 'z' to FileCacheArchive 'rE)r@rƒryÚcodecsr�Ú isinstanceÚbytesÚdecoderžrFr0rcr“rrN)rr(r$r)r#r r r r r*…s      ÿzFileCacheArchive.add_stringc Csž|j�„| |t¡}|s(WdƒdStj|ddd��}| |¡Wdƒn1sX0Y| d|›d|j›d�¡Wdƒn1s�0YdS)NÚwbr—zadded binary content at 'z' to archive 'rE)r@rƒryr¤r�ržrrN)rr(r$r r r r r+˜s ( ÿzFileCacheArchive.add_binaryc Csô| d|›d|›d�¡|j�h| |t¡}|s@WdƒdStj |¡sxt ||¡| d|›d|›d|j›d�¡Wdƒn1sŒ0Y| d|›d|›d |›�¡tj  |¡}tj  tj  ||¡¡}|  |¡}d d „}tj  |¡�sðtj |¡�r‚|}tj  |¡}tj  |t |¡¡}tj ||¡}|||ƒ�r\| d |›d |›d�¡dS| d|›d|›d�¡| ||¡nntj |¡�r®| d|›d�¡| |¡nBtj |¡�rÚ| d|›d�¡| |¡n| d|›d|›�¡dS)Nzadding symlink at 'r^rEzadded symlink at 'z' to 'z' in archive 'zLink follow up: source=z link_name=z dest=c Ss˜tj |¡}tj |¡s.tj tj ||¡¡}tj |¡}||krFdSzt |¡Wn>ty’}z&|jdkr|WYd}~dS‚WYd}~n d}~00dS)z†Return ``True`` if the symbolic link ``link_name`` is part of a file system loop, or ``False`` otherwise. Té(NF) rFr0ÚdirnamerSÚrealpathrMrpr›Úerrno)r-r,Zlink_dirr’r r r Úis_loop¹s    z*FileCacheArchive.add_link..is_loopzLink 'z' - 'z' loops: skipping...z Adding link z -> z for link follow upz Adding dir z Adding file zNo link follow up: source=)rr@rƒr|rFr0ÚlexistsrhrNrªr«rMrVrcrdrerHr.r_r1Úisfiler&) rr,r-r$Z source_dirZhost_path_nameZdest_path_namer­r�r r r r.£sJ   ÿ(ÿ       ÿzFileCacheArchive.add_linkcCs6|j�| |t¡Wdƒn1s(0YdS)zmCreate a directory in the archive. :param path: the path in the host file system to add N)r@rƒrvr/r r r r1êszFileCacheArchive.add_dirc Cs¢| |t¡}|sdStj |¡sžzt |||¡Wn^ty�}zF|jtjkrxd}|  d|›d|›d�¡WYd}~dS|‚WYd}~n d}~00|  ||¡dS)NzOperation not permittedz add_node: z - mknod 'rE) rƒr~rFr0rcÚmknodr›r¬ÚEPERMrr“)rr0r)r2r$r’rr r r r3ós   zFileCacheArchive.add_nodecCs&dtjvr"tjd}t |j|¡SdS)NÚ PC_NAME_MAXéÿ)rFÚpathconf_namesÚpathconfrN)rZ pc_name_maxr r r r5s  zFileCacheArchive.name_maxcCs|jSr©rNrr r r r4 szFileCacheArchive.get_tmp_dircCs|jSrr¶rr r r r6 sz!FileCacheArchive.get_archive_pathcCs8tjtj |j|¡|d�| d|›d|j›d�¡dS)zsCreate path, including leading components. Used by sos.sosreport to set up sos_* directories. r]zcreated directory at 'z' in FileCacheArchive 'rEN)rFrOr0rMrNr)rr0r)r r r rOs ÿzFileCacheArchive.makedirscCs| |¡}tj|dddd�S)NÚrr–r£)r˜Úerrors)rVr¤r�r/r r r Ú open_files zFileCacheArchive.open_filecCstj |j¡rt |j¡dSr)rFr0r_rNr‡Úrmtreerr r r r7szFileCacheArchive.cleanupcCsft ¡}|jj}||}|j d|¡|j d|¡|j d|¡| |jjdd�tj  dd¡¡dS) zŒAdds component-agnostic data to the manifest so that individual SoSComponents do not need to redundantly add these manually Zend_timeÚrun_timeÚ compressioné)ÚindentÚ sos_reportsz manifest.jsonN) rZnowrLZ start_timeZ add_fieldr*Zget_jsonrFr0rM)rr9ÚendÚstartr»r r r Úadd_final_manifest_data!s ÿz(FileCacheArchive.add_final_manifest_datacCsN| |j¡|_tj |j|j¡}t |j|¡||_tj |j| ¡¡|_ dS)zeRename the archive to an obfuscated version using an initialized SoSCleaner instance N) Zobfuscate_stringrrFr0rMrIÚrenamerNr Ú _archive_name)rZcleanerZ _new_rootr r r Úrename_archive_root.s z$FileCacheArchive.rename_archive_rootc Cs¬tjtjB}t|dƒr(|j}|j|B}n|}|}d}| |¡�}| ¡}Wdƒn1s\0Yt|t ƒs||  dd¡}tj ||||d�\} } | r¤|  | |¡nd} | S)aòApply a regexp substitution to a file in the archive. :param path: Path in the archive where the file can be found :type path: ``str`` :param regexp: A regex to match the contents of the file :type regexp: ``str`` or compiled ``re`` object :param subst: The substitution string to be used to replace matches within the file :type subst: ``str`` :returns: Number of replacements made :rtype: ``int`` ÚpatternrBNr¢r£)Úflagsr) ÚreÚ IGNORECASEÚ MULTILINEÚhasattrrÆrÇr¹r•r¥Ústrr§Úsubnr*) rr0ZregexpÚsubstZ common_flagsrÆrÇr(ÚreadableÚresultZ replacementsr r r Ú do_file_sub8s$    &   ÿ zFileCacheArchive.do_file_subc Csø| d|j›d|›d�¡z| |¡}Wn<tyd}z$| d|›�¡| ¡WYd}~Sd}~00| ¡| d|j›dt  |j¡j ›d�¡|j d�rðz |  |¡WSt�yì}z(d }| |›d |›�¡|WYd}~Sd}~00n|SdS) Nzfinalizing archive 'z' using method 'rEz+An error occurred compressing the archive: zbuilt archive at 'z' (size=ú)Zencryptz)An error occurred encrypting the archive:ú ) rrNÚ_build_archiver�rr r7rÄrFrpÚst_sizerJÚ_encrypt)rr9ÚresÚerrr’Zexp_msgr r r r:]s(ÿ  ÿ   zFileCacheArchive.finalizecCsò| dd¡}|d7}d|›d�}d}|jdrL|d|jd›d�7}||7}|jd rŒ|jd  d d ¡}d |i}|d 7}d|›d�}||7}t|d|dd�}|ddkr¬|S|ddkrÎ|jdrÈd}qæd}nd|d›d|d›�}t|ƒ‚dS)a÷Encrypts the compressed archive using GPG. If encryption fails for any reason, it should be logged by sos but not cause execution to stop. The assumption is that the unencrypted archive would still be of use to the user, and/or that the end user has another means of securing the archive. Returns the name of the encrypted archive, or raises an exception to signal that encryption failed and the unencrypted archive name should be used. z sosreport-zsecured-sosreport-z.gpgzgpg --batch -o rÓNÚkeyz--trust-model always -e -r Úpasswordz'"rBZsos_gpgz-c --passphrase-fd 0 z/bin/bash -c "echo $sos_gpg | ú"rT)ÚtimeoutÚenvÚstderrÚstatusézSpecified key not in keyringzCould not read passphrasezgpg exited with code z and error Úoutput)ÚreplacerJrr�)rÚarchiveZarc_nameZenc_cmdrÝÚpasswdr·rr r r rÖts,        zFileCacheArchive._encryptcCs| ¡Sr)r r8r r r rÔ�szFileCacheArchive._build_archive)N)rD)NF)NF)r')rD)r r;r<r=rIrNrÄrRrVrYrfrƒr“r&r*r+r.r1r3r5r4r6rOr¹r7rÂrÅrÑr:rÖrÔr r r r rA†s:ÿ  ] K $  G    %)rAcsTeZdZdZdZdZd‡fdd„ Zddd„Zdd „Zd d „Z d d „Z dd„Z ‡Z S)ÚTarFileArchivez: archive class using python TarFile to create tar archivesNFc s6tƒ |||||||¡d|_tj || ¡¡|_dS)NÚtar)ÚsuperrRÚ_suffixrFr0rMr rÄrP©Ú __class__r r rR§sÿÿzTarFileArchive.__init__cCsP|j|_|jd›|jd<|jd›|jd<|r4||_n|j|_|j|_|j |_ dS)Nz.9fZatimeÚctime) Úst_mtimeÚmtimeÚst_atimeÚ pax_headersÚst_ctimer)r{rŽÚuidr�Úgid)rZtar_infoÚfstatr)r r r Úset_tarinfo_from_stat°sz$TarFileArchive.set_tarinfo_from_statcs |jttj |j¡dƒd…‰ˆs*|j‰gd¢}t‡fdd„|DƒƒrLdSzt ˆ¡}Wntyp|YS0|j r�|  ˆ¡}|r�||j d<|  ||¡|S)Néÿÿÿÿ)z /version.txt$z/sos_logs(/.*)?z/sos_reports(/.*)?c3s|]}t |ˆ¡VqdSr)rÈÚmatch)Ú.0Úskip©Ú orig_pathr r Ú Âóz9TarFileArchive.copy_permissions_filter..zRHT.security.selinux) r ÚlenrFr0r`rNrorpr›Ú_with_selinux_contextÚget_selinux_contextrïrô)rÚtarinfoZskipsróÚcontextr rùr Úcopy_permissions_filter½s       z&TarFileArchive.copy_permissions_filtercCs.zt |¡\}}|WSty(YdS0dSr)ÚselinuxZ getfileconr�)rr0Ú_Úcr r r rÿÏs  z"TarFileArchive.get_selinux_contextcCs|j›d|j›�S)NÚ.)rNrèrr r r r ÖszTarFileArchive.namecCs&d}|dkr tdƒdurdnd}|dkr,d}|durn| d¡}|j›d|›�|_|jd|›�7_d |›�}id d id d idœ}tj|jfd|i||¤Ž�n}dD]B}tj tj  |j |¡¡r¤|j tj  |j |¡|j ›d|›�d�q¤|j |j |j |j d�Wdƒn1�s0Y| ¡S)Nr'ÚautoÚlzmaÚxzÚgzipZnoneÚiprzw:Ú compressleveléÚpreseté)Nr r r))z version.txtr¿Zsos_logsrC)Úarcname)rÚfilter)rÚstriprÄrèÚtarfiler�rFr0rcrMrNÚaddrrr )rr9Ú_modeZ _comp_modeÚkwargsræZ_contentr r r rÔÙs<  ý ÿþþ ÿ&zTarFileArchive._build_archive)N)N) r r;r<r=r9rþrRrôrrÿr rÔÚ __classcell__r r rér rå¡sÿ rå)rFrr‡r?r¤r¬rprÈrÚ threadingrÚimportlib.utilrZ sos.utilitiesrrÚ ImportErrorryr|r~rvZ P_CONTFILEr rArår r r r Ú s6      ]