a ì)g'«ã@s$ddlmZmZmZeZdZdZdZddl Z ddl Z ddl Z ddl Z ddl Z ddlZddlZddlZddlZddlZddlZddlZddlmZddlmZmZddlmZmZmZdd lmZdd l m!Z!dd l"m#Z#dd l$m%Z%zdd l&m'Z'Wn e(�ydd l)m'Z'Yn0e *d¡Z+e *d¡Z,e *d¡Z-e *d¡Z.e *d¡Z/e *d¡Z0e *d¡Z1e *d¡Z2e *d¡Z3dd„Z4dd„Z5Gdd„de6ƒZ7Gdd„de8ƒZ9Gdd „d e8ƒZ:Gd!d"„d"e:ƒZ;Gd#d$„d$e:ƒZGd)d*„d*e9ƒZ?d+d,„Z@d-d.„ZAeBd/k�r eAƒdS)0é)Úabsolute_importÚdivisionÚprint_functiona¦ --- module: unarchive version_added: '1.4' short_description: Unpacks an archive after (optionally) copying it from the local machine description: - The C(unarchive) module unpacks an archive. It will not unpack a compressed file that does not contain an archive. - By default, it will copy the source file from the local system to the target before unpacking. - Set C(remote_src=yes) to unpack an archive which already exists on the target. - If checksum validation is desired, use M(ansible.builtin.get_url) or M(ansible.builtin.uri) instead to fetch the file and set C(remote_src=yes). - For Windows targets, use the M(community.windows.win_unzip) module instead. options: src: description: - If C(remote_src=no) (default), local path to archive file to copy to the target server; can be absolute or relative. If C(remote_src=yes), path on the target server to existing archive file to unpack. - If C(remote_src=yes) and C(src) contains C(://), the remote machine will download the file from the URL first. (version_added 2.0). This is only for simple cases, for full download support use the M(ansible.builtin.get_url) module. type: path required: true dest: description: - Remote absolute path where the archive should be unpacked. - The given path must exist. Base directory is not created by this module. type: path required: true copy: description: - If true, the file is copied from local controller to the managed (remote) node, otherwise, the plugin will look for src archive on the managed machine. - This option has been deprecated in favor of C(remote_src). - This option is mutually exclusive with C(remote_src). type: bool default: yes creates: description: - If the specified absolute path (file or directory) already exists, this step will B(not) be run. - The specified absolute path (file or directory) must be below the base path given with C(dest:). type: path version_added: "1.6" io_buffer_size: description: - Size of the volatile memory buffer that is used for extracting files from the archive in bytes. type: int default: 65536 version_added: "2.12" list_files: description: - If set to True, return the list of files that are contained in the tarball. type: bool default: no version_added: "2.0" exclude: description: - List the directory and file entries that you would like to exclude from the unarchive action. - Mutually exclusive with C(include). type: list default: [] elements: str version_added: "2.1" include: description: - List of directory and file entries that you would like to extract from the archive. If C(include) is not empty, only files listed here will be extracted. - Mutually exclusive with C(exclude). type: list default: [] elements: str version_added: "2.11" keep_newer: description: - Do not replace existing files that are newer than files from the archive. type: bool default: no version_added: "2.1" extra_opts: description: - Specify additional options by passing in an array. - Each space-separated command-line option should be a new element of the array. See examples. - Command-line options with multiple elements must use multiple lines in the array, one for each element. type: list elements: str default: "" version_added: "2.1" remote_src: description: - Set to C(true) to indicate the archived file is already on the remote system and not local to the Ansible controller. - This option is mutually exclusive with C(copy). type: bool default: no version_added: "2.2" validate_certs: description: - This only applies if using a https URL as the source of the file. - This should only set to C(false) used on personally controlled sites using self-signed certificate. - Prior to 2.2 the code worked as if this was set to C(true). type: bool default: yes version_added: "2.2" extends_documentation_fragment: - action_common_attributes - action_common_attributes.flow - action_common_attributes.files - decrypt - files attributes: action: support: full async: support: none bypass_host_loop: support: none check_mode: support: partial details: Not supported for gzipped tar files. diff_mode: support: partial details: Uses gtar's C(--diff) arg to calculate if changed or not. If this C(arg) is not supported, it will always unpack the archive. platform: platforms: posix safe_file_operations: support: none vault: support: full todo: - Re-implement tar support using native tarfile module. - Re-implement zip support using native zipfile module. notes: - Requires C(zipinfo) and C(gtar)/C(unzip) command on target host. - Requires C(zstd) command on target host to expand I(.tar.zst) files. - Can handle I(.zip) files using C(unzip) as well as I(.tar), I(.tar.gz), I(.tar.bz2), I(.tar.xz), and I(.tar.zst) files using C(gtar). - Does not handle I(.gz) files, I(.bz2) files, I(.xz), or I(.zst) files that do not contain a I(.tar) archive. - Existing files/directories in the destination which are not in the archive are not touched. This is the same behavior as a normal archive extraction. - Existing files/directories in the destination which are not in the archive are ignored for purposes of deciding if the archive should be unpacked or not. seealso: - module: community.general.archive - module: community.general.iso_extract - module: community.windows.win_unzip author: Michael DeHaan au - name: Extract foo.tgz into /var/lib/foo ansible.builtin.unarchive: src: foo.tgz dest: /var/lib/foo - name: Unarchive a file that is already on the remote machine ansible.builtin.unarchive: src: /tmp/foo.zip dest: /usr/local/bin remote_src: yes - name: Unarchive a file that needs to be downloaded (added in 2.0) ansible.builtin.unarchive: src: https://example.com/example.zip dest: /usr/local/bin remote_src: yes - name: Unarchive a file with extra options ansible.builtin.unarchive: src: /tmp/foo.zip dest: /usr/local/bin extra_opts: - --transform - s/^xxx/yyy/ a_ dest: description: Path to the destination directory. returned: always type: str sample: /opt/software files: description: List of all the files in the archive. returned: When I(list_files) is True type: list sample: '["file1", "file2"]' gid: description: Numerical ID of the group that owns the destination directory. returned: always type: int sample: 1000 group: description: Name of the group that owns the destination directory. returned: always type: str sample: "librarians" handler: description: Archive software handler used to extract and decompress the archive. returned: always type: str sample: "TgzArchive" mode: description: String that represents the octal permissions of the destination directory. returned: always type: str sample: "0755" owner: description: Name of the user that owns the destination directory. returned: always type: str sample: "paul" size: description: The size of destination directory in bytes. Does not include the size of files or subdirectories contained within. returned: always type: int sample: 36 src: description: - The source archive's path. - If I(src) was a remote web URL, or from the local ansible controller, this shows the temporary location where the download was stored. returned: always type: str sample: "/home/paul/test.tar.gz" state: description: State of the destination. Effectively always "directory". returned: always type: str sample: "directory" uid: description: Numerical ID of the user that owns the destination directory. returned: always type: int sample: 1000 N)Úpartial)ÚZipFileÚ BadZipfile)Úto_bytesÚ to_nativeÚto_text)Ú AnsibleModule)Ú get_bin_path)Úget_best_parsable_locale)Ú fetch_file)Úquotez: Uid differs$z: Gid differs$z: Mode differs$z: Mod time differs$z4: : Warning: Cannot stat: No such file or directory$z2: Warning: Cannot stat: No such file or directory$z([r-][w-][SsTtx-]){3}z: Invalid ownerz: Invalid groupcCs`t d¡}t|dƒ�4}tt|j|ƒdƒD]}t ||¡}q(Wdƒn1sN0Y|d@S)z# Return a CRC32 checksum of a file óÚrbNlÿÿ)ÚbinasciiÚcrc32ÚopenÚiterrÚread)ÚpathZ buffer_sizeÚcrcÚfZb_block©rú=/usr/lib/python3.9/site-packages/ansible/modules/unarchive.pyrs   ,rcCst dd|¡S)z6 Quote meta-characters in the args for the unix shell z([^A-Za-z0-9_])z\\\1)ÚreÚsub)ÚstringrrrÚ shell_escape%src@s eZdZdS)ÚUnarchiveErrorN)Ú__name__Ú __module__Ú __qualname__rrrrr *sr c@sPeZdZdd„Zdd„Zdd„Zdd„Zed d „ƒZd d „Z d d„Z dd„Z dS)Ú ZipArchivecCsz||_||_||_|jd|_||_|jd|_|jd|_g|_|jjd|_ d|_ d|_ g|_ t ƒ|_d|_d|_dS)NÚ extra_optsÚio_buffer_sizeÚexcludeÚincludeÚ)©ÚunzipÚcmd_path)ÚzipinfoÚzipinfo_cmd_path)ÚsrcÚb_destÚ file_argsÚparamsÚoptsÚmoduler&ÚexcludesÚincludesÚ include_filesr,r.Ú_files_in_archiveÚdictÚ _infodictÚ zipinfoflagÚbinaries©Úselfr/r0r1r4rrrÚ__init__0s   zZipArchive.__init__cCsd|ddd…}d}tddƒD]<}tddƒD],}||d|dvr*|d|d|7}q*q||@S)zA Convert a Unix permission string (rw-r--r--) into a mode (0644) Néÿÿÿÿré)ÚrÚwÚxÚsÚté)Úrange)r>ZmodestrÚumaskZrevstrÚmodeÚjÚirrrÚ_permstr_to_octalDszZipArchive._permstr_to_octalcCsz|j |jd|jg¡\}}}|r.td|jƒ‚| ¡dd…D]6}| dd¡}|j |d¡t |dƒ|j |d<q>dS)Nz-vz,Neither python zipfile nor unzip can read %srAéþÿÿÿéé) r4Ú run_commandr,r/r Ú splitlinesÚsplitr8ÚappendÚintr:)r>ÚrcÚoutÚerrÚlineÚfieldsrrrÚ_legacy_file_listQs zZipArchive._legacy_file_listc Cs¶|jr|j|Szt|jƒ}WnDtyb}z,|jd ¡ d¡rL| ¡n‚WYd}~nRd}~00z$| ¡D]}t |j ƒ|j|j <qnWn"t yª|  ¡tdƒ‚Yn0|j|S)Nrúbad magic numberz#Unable to list files in the archive)r:rr/rÚargsÚlowerÚ startswithr[ÚinfolistrUZCRCÚfilenameÚ ExceptionÚcloser )r>rÚarchiveÚeÚitemrrrÚ_crc32[s    zZipArchive._crc32c Cs4|jr |jSg|_zt|jƒ}WnDtyd}z,|jd ¡ d¡rN| ¡n‚WYd}~nÒd}~00z€| ¡D]r}|j r¤|j D] }t   ||¡r€|j  t |ƒ¡q€qpd}|j rÎ|j D]}t   ||¡r´d}qÎq´|sp|j  t |ƒ¡qpWn>t�y$}z$| ¡tdt |ƒƒ‚WYd}~n d}~00| ¡|jS)Nrr\FTú'Unable to list files in the archive: %s)r8rr/rr]r^r_r[Znamelistr7ÚfnmatchrTr r5rbrcr )r>rdreÚmemberr(Ú exclude_flagr'rrrÚfiles_in_archivers8      &zZipArchive.files_in_archivec,Cs2 |jr|j|jdd|jg}n|jdd|jg}|jrD| dg|j¡|jrV| |j¡|j |¡\}}}|}d}d}|dkr‚d}nd}t  d¡}t  |¡t   ¡} t  ¡} t  ¡} t ¡} zt | ¡j} Wnttfyä| } Yn0zt | ¡j}Wntttf�y| }Yn0d}}|jd�r zt |jd¡}WnRt�y�zt t|jdƒ¡}Wn$tttf�yŠt | ¡}Yn0Yn0|j}|j}n"z| }Wnt�y¼Yn0| }d}}|jd �rPzt |jd ¡}WnVttf�y@zt t|jd ƒ¡}Wn$tttf�y:t | ¡}Yn0Yn0|j}|j}n"z|}Wnt�ylYn0| }|  ¡D�]”}d}| !dd ¡}t"|ƒd k�r¢�qzt"|dƒd k�rÊt"|dƒd k�rÊ�qzt"|d ƒdk�rà�qz|dddv�szt#|ddd…ƒ $d¡�s�qz|dd}|ddd…}|d}|d}t|dƒ}t%|d dd�}||jv�rv|d|7}�qz|ddk�r¤|dk�rž|d||f7}d}n.|dk�r´d}n|dk�rÄd}n|dk�rÒd}t"|ƒd k�r|ddk�rôd }n|d!k�rd }nd"}|}nd#|  &¡v�r"|}nd}t"|ƒd$k�s@t' (|¡�sLt)d%|ƒ‚tj* +|j,t-|dd�¡} zt .| ¡}!WnFt�y¸d}|j/ 0|¡|d&|7}|d'||f7}Y�qzYn0|dk�rt1 2|!j3¡�sd}|j/ 0|¡|d(|7}|d)||f7}�qz|dk�rNt1 4|!j3¡�sNd}d}|j/ 0|¡|d*|7}|d)||f7}�qz|dk�r–t1 5|!j3¡�s–d}|j/ 0|¡|d+|7}|d)||f7}�qzt6d,|ƒ}"t7j7t8 9|d d-¡dd …Ž}#t8 :|# ;¡¡}$t1 4|!j3¡�rŒ|jjk�rÆd}|d4|||!j>f7}d5|"d<t1 4|!j3¡�rt?| |j@ƒ}%|%| A|¡k�rd}|d6|| A|¡|%f7}d7|"d<|dk�r>|jd8�râtB|jd8tƒ�rH|jd8}&n˜zt|jd8d ƒ}&Wn‚t�yÞ}'zhztC D|!|jd8¡}&WnDt�yÈ}'z*|jjE|d9tF|'ƒtG H¡d:�WYd}'~'n d}'~'00WYd}'~'n d}'~'00n$|dk�rú| I|d¡}&n | I||¡}&|&t1 J|!j3¡k�r>d}d;|"d<<|d=||&t1 J|!j3¡f7}d}(})zt |!jK¡j}(Wnttf�yv|!jK})Yn0| dk�r¨|| k�s–|| k�r¨t)d>||| fƒ‚|(�rØ|(|k�rØd}|d?||(|f7}d@|"d <n.|)� r|)|k� rd}|dA||)|f7}d@|"d <d}*}+zt |!jL¡j}*Wn tttf� y@|!jL}+Yn0| dk� r|||k� s`|| k� r||| v� r|t)dB||| fƒ‚|*� r¬|*|k� r¬d}|dC||*|f7}dD|"d <n.|+� rÚ|+|k� rÚd}|dE||+|f7}dD|"d <|�rz||j/v� rø|j/ 0|¡|dFd +|"¡|f7}�qz|j/� rd}tM||||||dG�S)HNz-Tz-sú-xr)rTFÚownerÚgrouprOéé rPézdl-?ézrwxstah-rGrAÚsurrogate_or_strict©ÚerrorszPath %s is excluded on request r@ú/Údz8Path %s incorrectly tagged as "%s", but is a directory. ÚlÚLú-rú?Z rwxrwxrwxzrwx---z rw-rw-rw-Úbsdé z"ZIP info perm format incorrect, %szPath %s is missing z>%s++++++.?? %s z/File %s already exists, but not as a directory zc%s++++++.?? %s z7Directory %s already exists, but not as a regular file z2Directory %s already exists, but not as a symlink z .%s.......??z %Y%m%d.%H%M%SÚ keep_newerz!File %s is older, replacing file rFéz!File %s is newer, excluding file z$File %s differs in mtime (%f vs %f) z#File %s differs in size (%d vs %d) rEz5File %s differs in CRC32 checksum (0x%08x vs 0x%08x) ÚcrJz%s)rÚmsgÚ exceptionÚpéz*Path %s differs in permissions (%o vs %o) z/Cannot change ownership of %s to %s, as user %sz8Path %s is owned by user %s, not by user %s as expected Úoz6Path %s is owned by uid %s, not by uid %s as expected z5Cannot change group ownership of %s to %s, as user %sz:Path %s is owned by group %s, not by group %s as expected Úgz6Path %s is owned by gid %s, not by gid %s as expected z%s %s )Ú unarchivedrVrWrXÚcmdÚdiff)Nr;r.r/r5Úextendr7r4rQÚosrIÚplatformÚsystemÚ getgroupsÚgetuidÚgetgidÚpwdÚgetpwuidÚpw_nameÚ TypeErrorÚKeyErrorÚgrpÚgetgrgidÚgr_nameÚ ValueErrorÚ OverflowErrorr1ÚgetpwnamrUÚpw_uidrbÚgetgrnamÚgr_gidrRrSÚlenÚ frozensetÚissubsetr r^ÚZIP_FILE_MODE_REÚmatchr rÚjoinr0rÚlstatr6rTÚstatÚS_ISDIRÚst_modeÚS_ISREGÚS_ISLNKÚlistÚdatetimeÚtimeÚstrptimeÚmktimeZ timetupler2Úst_mtimeÚst_sizerr&rgÚ isinstancer Z_symbolic_mode_to_octalÚ fail_jsonr Ú tracebackÚ format_excrMÚS_IMODEÚst_uidÚst_gidr9),r>r‰rVrWrXÚold_outrŠrˆrIZ systemtypeÚgroupsÚrun_uidZrun_gidZ run_ownerZ run_groupZ fut_ownerZfut_uidZtpwZ fut_groupZfut_gidZtgrrYZchangeZpcsZztypeZpermstrÚversionZostypeÚsizerZftypeZ file_umaskr0ÚstZitemizedZ dt_objectZ timestamprrJrernÚuidroÚgidrrrÚ is_unarchived˜s¬        $.                                 L     (   zZipArchive.is_unarchivedcCs„|jdg}|jr| |j¡| |j¡|jr@| dg|j¡|jrR| |j¡| d|jg¡|j  |¡\}}}t ||||d�S)Nz-ormz-d©r‰rVrWrX) r,r3r‹rTr/r5r7r0r4rQr9)r>r‰rVrWrXrrrÚ unarchiveÌs    zZipArchive.unarchivec Cs¦g}|jD]B}zt||dt|dƒƒWq tyJ| |d¡Yq 0q |rhddjd |¡d�fS|jd|jg}|j   |¡\}}}|dkr”dSdd |j|ffS) NrsrFz7Unable to find required '{missing}' binary in the path.z' or ')Úmissingz-l©TNú)Command "%s" could not handle archive: %s) r<Úsetattrr ršrTÚformatr¥r,r/r4rQ)r>rÅÚbr‰rVrWrXrrrÚcan_handle_archiveÝs  zZipArchive.can_handle_archiveN) r!r"r#r?rMr[rgÚpropertyrlrÂrÄrËrrrrr$.s   %6r$c@s@eZdZdd„Zdd„Zedd„ƒZdd„Zd d „Zd d „Z d S)Ú TgzArchivecCs†||_||_||_|jd|_||_|jjrD|jjdd|jjd�dd„|jjdDƒ|_ |jjd|_ d|_ d|_ d |_ g|_dS) Nr%Tz>remote module (%s) does not support check mode when using gtar)Zskippedr‚cSsg|]}| d¡‘qS)rw)Úrstrip)Ú.0rrrrÚ ùrz'TgzArchive.__init__..r'r(z-z)r/r0r1r2r3r4Ú check_modeÚ exit_jsonÚ_namer5r7r,Útar_typeÚzipflagr8r=rrrr?ñs zTgzArchive.__init__cCsJ|jdg}|j |¡\}}}d}| d¡r0d}n| d¡rFd|vrFd}|S)Nz --versionZbsdtarr}ÚtarZGNUÚgnu)r,r4rQr_)r>r‰rVrWrXrÔrrrÚ _get_tar_types  zTgzArchive._get_tar_typec CsJ|jr |jS|jdd|jg}|jr.| |j¡|jrF| dg|j¡|jrb| dd„|jDƒ¡| d|jg¡|j r„| |j ¡t |j ƒ}|j j ||jt ||||d�d�\}}}|d krÈtd |ƒ‚| ¡D]r}tt |¡d ƒ}| d ¡rü|d d…}d }|j�r.|jD]}t ||¡�rd}�q.�q|sÐ|j t|ƒ¡qÐ|jS)Nz--listú-Cú--show-transformed-namescSsg|] }d|‘qS©z --exclude=r©rÏrrrrrÐrz/TgzArchive.files_in_archive..ú-f©ÚLANGÚLC_ALLÚ LC_MESSAGESÚLANGUAGE©ÚcwdZenviron_updaterrhrwrsFT)r8r,r0rÕrTr3r‹r5r/r7r r4rQr9r rRr ÚcodecsÚ escape_decoder_ri) r>r‰ÚlocalerVrWrXrarkr'rrrrl s:   &      zTgzArchive.files_in_archivec Cs:|jdd|jg}|jr"| |j¡|jr:| dg|j¡|jdr\| dt|jdƒ¡|jdr~| dt|jdƒ¡|jj dr”| d ¡|j r°| d d „|j Dƒ¡| d |j g¡|j rÒ| |j ¡t |jƒ}|jj||jt||||d �d�\}}}d}|}d}t ¡}| ¡| ¡D]ö} t | ¡�r:�q&|dk�rh|jd�sht | ¡�rh|| d7}|dk�r–|jd�s–t | ¡�r–|| d7}|jd�sºt | ¡�rº|| d7}t | ¡�rÒ|| d7}t | ¡�rê|| d7}t | ¡�r|| d7}t | ¡�r&|| d7}�q&|�r(d}t|||||d�S)Nz--diffrÙrÚrnú--owner=roú--group=rú--keep-newer-filescSsg|] }d|‘qSrÛrrÜrrrrÐCrz,TgzArchive.is_unarchived..rÝrÞrãTr)rÚ rJF)rˆrVrWrXr‰)r,r0rÕrTr3r‹r1rr4r2r5r/r7r rQr9rŒr�rRÚ EMPTY_FILE_REÚsearchÚ OWNER_DIFF_REÚ GROUP_DIFF_REÚ MODE_DIFF_REÚMOD_TIME_DIFF_REÚMISSING_FILE_REÚINVALID_OWNER_REÚINVALID_GROUP_RE) r>r‰rçrVrWrXrˆrºr¼rYrrrrÂ6sT       & " "         zTgzArchive.is_unarchivedc Cs|jdd|jg}|jr"| |j¡|jr:| dg|j¡|jdr\| dt|jdƒ¡|jdr~| dt|jdƒ¡|jj dr”| d ¡|j r°| d d „|j Dƒ¡| d |j g¡|j rÒ| |j ¡t |jƒ}|jj||jt||||d �d�\}}}t||||d�S)Nz --extractrÙrÚrnrèrorérrêcSsg|] }d|‘qSrÛrrÜrrrrÐyrz(TgzArchive.unarchive..rÝrÞrãrÃ)r,r0rÕrTr3r‹r1rr4r2r5r/r7r rQr9)r>r‰rçrVrWrXrrrrÄls&       &zTgzArchive.unarchivec CsÊztdƒ|_Wn8tyFztdƒ|_Wnty@YYdS0Yn0| ¡|_|jdkrpdd|j|jffSz|jr~WdSWn:tyº}z"dd|jt|ƒffWYd}~Sd}~00dd |jfS) NZgtarrÖ)Fz:Unable to find required 'gtar' or 'tar' binary in the pathr×Fz7Command "%s" detected as tar type %s. GNU tar required.rÆrÇzNCommand "%s" found no files in archive. Empty archive files are not supported.)r r,ršrØrÔrlr r )r>rerrrrË�s      ,zTgzArchive.can_handle_archiveN) r!r"r#r?rØrÌrlrÂrÄrËrrrrrÍïs  +6rÍcseZdZ‡fdd„Z‡ZS)Ú TarArchivecs tt|ƒ ||||¡d|_dS)Nr))Úsuperrõr?rÕr=©Ú __class__rrr?�szTarArchive.__init__©r!r"r#r?Ú __classcell__rrr÷rrõœsrõcseZdZ‡fdd„Z‡ZS)ÚTarBzipArchivecs tt|ƒ ||||¡d|_dS)Nz-j)rörûr?rÕr=r÷rrr?¥szTarBzipArchive.__init__rùrrr÷rrû¤srûcseZdZ‡fdd„Z‡ZS)Ú TarXzArchivecs tt|ƒ ||||¡d|_dS)Nz-J)rörür?rÕr=r÷rrr?¬szTarXzArchive.__init__rùrrr÷rrü«srücseZdZ‡fdd„Z‡ZS)ÚTarZstdArchivecs tt|ƒ ||||¡d|_dS)Nz--use-compress-program=zstd)rörýr?rÕr=r÷rrr?³szTarZstdArchive.__init__rùrrr÷rrý²srýcs(eZdZ‡fdd„Z‡fdd„Z‡ZS)Ú ZipZArchivecs&tt|ƒ ||||¡d|_d|_dS)Nz-Z)r*)r+r.)rörþr?r;r<r=r÷rrr?¿szZipZArchive.__init__csXtt|ƒ ¡\}}|s||fS|j|jg}|j |¡\}}}d| ¡vrLdSdd|fS)Nr-rÆFz/Command "unzip -Z" could not handle archive: %s)rörþrËr.r;r4rQr^)r>Zunzip_availableZ error_msgr‰rVrWrXr÷rrrËÇs  zZipZArchive.can_handle_archive)r!r"r#r?rËrúrrr÷rrþ¾s rþc Csttttttttg}tƒ}|D]4}|||||ƒ}| ¡\}} |rF|S|  | ¡qd  |¡} |j d|| fd�dS)NrëzdFailed to find handler for "%s". Make sure the required command to extract the file is installed. %s©r‚) r$rþrÍrõrûrürýÚsetrËÚaddr¥r´) r/Údestr1r4ÚhandlersZreasonsÚhandlerÚobjZ can_handleÚreasonZ reason_msgrrrÚ pick_handlerÖs   rcCs,tttddd�tddd�tddd�tdd�tddd�tddd�tdd gd �tdd gd �tdd gd �tddd�td d d�tddd�tddd�d � dddgd�}|jd}|jd}t|dd�}|jd}| |j¡}tj |¡�s|sö|jd|d�n&d|v�r t ||ƒ}n|jd|d�t  |tj ¡�s<|jd|d�z&tj  |¡dk�r`|jd|d�Wn>t �y }z$|jd|t|ƒfd�WYd}~n d}~00tj |¡�sÀ|jd|d�t||||ƒ}t|jj||d�}| ¡} |j�r| d |d <nŒ| d�rd|d <nxz>| ¡|d!<|d!d"dk�rP|jfd#d$||fi|¤ŽWn0t�y‚|jfd#d$||fi|¤ŽYn 0d|d <|  d%d¡�rªd&| d%i|d%<| d%d¡�r|j�sg} |jD]°} tj |t| dd�¡|d<z|j||d dd'�|d <WnFttf�yJ}z(|jfd#d(t|ƒi|¤ŽWYd}~n d}~00d)| v�rÊ|  d)¡d} | | v�rÊ|  | ¡�qÊ| �r| D]z} d*|| f|d<z|j||d dd'�|d <WnFttf�yü}z(|jfd#d(t|ƒi|¤ŽWYd}~n d}~00�q†|jd+�r|j|d,<|jfi|¤ŽdS)-NrT)ÚtypeÚrequiredÚboolF)rÚdefault)rr¬Ústr)rÚelementsr rUi) r/rÚ remote_srcZcreatesÚ list_filesrr'r(r%Zvalidate_certsr&ÚcopyZdecrypt)r(r')Z argument_specZadd_file_common_argsZsupports_check_modeZmutually_exclusiver/rrtrurzSource '%s' failed to transferrÿz://zSource '%s' does not existzSource '%s' not readablerz)Invalid archive '%s', the file is 0 byteszSource '%s' not readable, %sz#Destination '%s' is not a directory)rrr/rˆZchangedZextract_resultsrVr‚zfailed to unpack %s to %srŠZprepared)Úexpandz1Unexpected error when accessing exploded file: %srwz%s/%srÚfiles)r r9r2rZload_file_common_argumentsrŒrÚexistsr´rÚaccessÚR_OKÚgetsizerbr Úisdirrrør!rÂrÑrÄÚIOErrorÚgetrlr¥Zset_fs_attributes_if_differentÚOSErrorrSrTrÒ)r4r/rr0rr1rerZres_argsZ check_resultsZ top_foldersraZtop_folder_pathrrrrÚmainãsœ            ïè       .    " 2  6  rÚ__main__)CZ __future__rrrrZ __metaclass__Z DOCUMENTATIONZEXAMPLESZRETURNrrår­rir—rŒr�r’rr§r®rµÚ functoolsrÚzipfilerrZansible.module_utils._textrr r Zansible.module_utils.basicr Z#ansible.module_utils.common.processr Z"ansible.module_utils.common.localer Zansible.module_utils.urlsrZshlexrÚ ImportErrorZpipesÚcompilerîrïrðrñrìròr£rórôrrrbr Úobjectr$rÍrõrûrürýrþrrr!rrrrÚ sn<               D.  w