
    ]&                        S r SSKJr  SSKJr  SSKJr  SSKrSSKrSSKrSSKJ	r	  SSK
Jr  SSKJr  SS	KJr  SS
KJr  SSKJr  Sr " S S\R(                  5      r " S S\5      rS rSS jrSS jrSS jrSS jrS rS r\" 5       r\RA                  S5      r!\RA                  S5      r"\RA                  S5      r#SS jr$g)a  Utilities that augment the core CRC32C functionality for storage commands.

The core CRC32C utility provides a hashlib-like functionality for CRC32C
calculation but will at times fall back to a slow, all-Python implementation.
This utility provides several mitigation strategies to avoid relying on the slow
implementation of CRC32C, including adding a "deferred" strategy that uses the
component gcloud-crc32c on files after they are downloaded.
    )absolute_import)division)unicode_literalsN)info_holder)errors)crc32c)binary_operations)log)
propertieszgcloud-crc32cc                   6   ^  \ rS rSrSrU 4S jrSS jrSrU =r$ )GcloudCrc32cOperation,   z1Operation for hashing a file using gcloud-crc32c.c                 :   > [         [        U ]
  " SS[        0UD6  g )Nbinary )superr   __init__BINARY_NAME)selfkwargs	__class__s     :lib/googlecloudsdk/command_lib/storage/fast_crc32c_util.pyr   GcloudCrc32cOperation.__init__/   s    	
/M{MfM    c                 4    S[        U5      S[        U5      U/$ )Nz-oz-l)str)r   	file_pathoffsetlengthr   s        r   _ParseArgsForCommand*GcloudCrc32cOperation._ParseArgsForCommand2   s    #f+tS[)<<r   r   )r   r   )	__name__
__module____qualname____firstlineno____doc__r   r    __static_attributes____classcell__)r   s   @r   r   r   ,   s    9N= =r   r   c                   @    \ rS rSrSrSS jrS rS rS rS r	S r
S	rg
)DeferredCrc32c6   zHashlib-like helper for deferring hash calculations to gcloud-crc32c.

NOTE: Given this class relies on analyzing data on disk, it is not appropriate
for hashing streaming downloads and will fail to work as expected.
c                     Xl         g)z{Sets up the internal checksum variable and allows an initial value.

Args:
  crc (int): The initial checksum to be stored.
N_crc)r   crcs     r   r   DeferredCrc32c.__init__=   s	     Ir   c                 (    [        U R                  S9$ )N)r/   )r*   r.   r   s    r   copyDeferredCrc32c.copyE   s    dii((r   c                     Ag )Nr   )r   datas     r   updateDeferredCrc32c.updateH   s    
r   c                     Ub  Uc  [         R                  " S5      e[        5       nU" XUS9nUR                  (       a  SU l        g[	        UR
                  5      U l        g)aU  Calculates checksum on a provided file path.

Args:
  file_path (str): A string representing a path to a file.
  offset (int): The number of bytes to offset from the beginning of the
    file. Defaults to 0.
  length (int): The number of bytes to read into the file. If not specified
    will calculate until the end of file is encountered.
NzIgcloud_crc32c binary uses 0 (not `None`) to indicate "no argument given.")r   r   r   r   )r   Errorr   failedintstdoutr.   )r   r   r   r   crc32c_operationresults         r   sum_fileDeferredCrc32c.sum_fileM   sV     ~LL"  -.	PF]]DIFMM(:DIr   c                 D    [         R                  " SU R                  5      $ )zReturns the checksum in big-endian order, per RFC 4960.

See: https://cloud.google.com/storage/docs/json_api/v1/objects#crc32c

Returns:
  An eight-byte digest string.
z>L)structpackr.   r2   s    r   digestDeferredCrc32c.digest`   s     ;;tTYY''r   c                 V    SR                  U R                  5      R                  S5      $ )zReturns a checksum like `digest` except as a bytestring of double length.

Returns:
  A sixteen byte digest string, containing only hex digits.
z{:08x}ascii)formatr.   encoder2   s    r   	hexdigestDeferredCrc32c.hexdigestj   s"     ??499%,,W55r   r-   N)r   )r"   r#   r$   r%   r&   r   r3   r7   r@   rE   rK   r'   r   r   r   r*   r*   6   s%    )
;&(6r   r*   c                  z     [         [        R                  " [         5      ;   $ ! [        R                   a     gf = f)zCReturns if gcloud-crc32c is installed and does not attempt install.F)r   r	   CheckForInstalledBinaryMissingExecutableExceptionr   r   r   _is_gcloud_crc32c_installedrP   s   s6    +CCKPPP		5	5 s    # ::c                 :    [         [        R                  " [         U S9;   $ ! [        R                   aL    [        R
                  " S5        [        R                  R                  R                  R                  S5         g  [        R
                  " S5         g= f)zCReturns True if gcloud-crc32c is installed and optionally installs.install_if_missingzygcloud-crc32c can not be found on the path. The user may have opted out of installation or lack component manager access.Fz.Failed to check if gcloud-crc32c is available.)r   r	   rN   rO   r
   debugr   VALUESstorageuse_gcloud_crc32cSetrR   s    r   !_check_if_gcloud_crc32c_availablerY   {   s    @+CC(:   
	5	5 	;
 II	A //33E: 
@II>?	s   " ABBc                     [         R                  =(       dF    [        R                  R                  R
                  R                  5       SL=(       a    [        U 5      $ )NF)r   IS_FAST_GOOGLE_CRC32C_AVAILABLEr   rU   rV   rW   GetBoolrY   rR   s    r   check_if_will_use_fast_crc32cr]      sG    		/	/ 
1199;5H @
+,>
?	r   c                     [         R                  R                  R                  R	                  5       nUSL a  gUc  [
        R                  (       a  gU (       a	  [        SS9$ [        5       $ )zReturns True if gcloud-crc32c should be used and installs if needed.

Args:
  install_if_missing (bool): Install gcloud-crc32c if not already present.

Returns:
  True if the Go binary gcloud-crc32c should be used.
FTrR   )	r   rU   rV   rW   r\   r   r[   rY   rP   )rS   user_wants_gcloud_crc32cs     r   should_use_gcloud_crc32cr`      s]     1199;  &&,,,EE	$	&&r   c                 b    [        SS9nU(       a
  [        5       $ [        R                  " U 5      $ )aD  Wraps the crc32c.get_crc32c() method to allow fallback to gcloud-crc32c.

DO NOT USE for streaming downloads, as this relies on file-based hashing and
does not take whether or not streaming is enabled into account.

Args:
  initial_data (bytes): The CRC32C object will be initialized with the
    checksum of the data.

Returns:
  A DeferredCrc32c instance if hashing can be deferred. Otherwise it returns a
  google_crc32c.Checksum instance if google-crc32c
  (https://github.com/googleapis/python-crc32c) is available and a
  predefined.Crc instance from crcmod library if not.
TrR   )r`   r*   r   
get_crc32c)initial_datashould_defers     r   rb   rb      s)      *TB,)	Nv/@/@/NNr   c                      [         R                  " 5       n U R                  R                  nU(       aG  [        R
                  R                  USS5      nSR                  U R                  R                  U5      $ g)zReturns the command to install google-crc32c library.

This will typically only be called if gcloud-crc32c is missing and can't be
installed for some reason. It requires user intervention which is why it's
not a preferred option.
libthird_partyz5{} -m pip install google-crc32c --upgrade --target {}N)
r   
InfoHolderinstallationsdk_rootospathjoinrI   basicpython_location)sdk_inforj   third_party_paths      r   !get_google_crc32c_install_commandrr      sc     ##%(""++(ww||He]CBII&&(8: :	r   c                  ~    [        5       n Sn[        R                  " SR                  U (       a  U S95      $ US95      $ )z CRC32C warnings share this text.z'gcloud components install gcloud-crc32cz      This copy {{}} since fast hash calculation tools
      are not installed. You can change this by running:
      	$ {crc32c_step}
      You can also modify the "storage/check_hashes" config setting.)crc32c_step)rr   textwrapdedentrI   )google_crc32c_install_stepgcloud_crc32c_install_steps     r   _get_hash_check_warning_basery      se      ABH	H IO' 1 IO I

 
 * IO I

 
r   zwill not be validatedzmay be slowzwas skippedc                 $   [        SS9(       a  g[        R                  R                  R                  R                  5       nU[        R                  R                  R                  :X  a"  U (       a  [        R                  " [        5        gU[        R                  R                  R                  :X  a  [        R                  " [        5        gU[        R                  R                  R                  :X  a  [        R                   " ["        5      eg)a  Informs user about slow hashing if requested.

Args:
  warn_for_always (bool): User may not want to see a warning about slow hashes
    if they have the "always check hashes" property set because (1) they
    intentionally set a property and (2) it could duplicate a warning in
    FileDownloadTask.

Raises:
  errors.Error: IF_FAST_ELSE_FAIL set, and CRC32C binary not present. See
    error message for more details.
TrR   N)r]   r   rU   rV   check_hashesGetCheckHashesALWAYSvaluer
   warning_SLOW_HASH_CHECK_WARNINGIF_FAST_ELSE_SKIP_NO_HASH_CHECK_WARNINGIF_FAST_ELSE_FAILr   r:   _NO_HASH_CHECK_ERROR)warn_for_alwaysr{   s     r   log_or_raise_crc32c_issuesr      s     #d;
""**77;;=,Z++22888_KK()z--??EEEKK&'z--??EEE
,,+
,, Fr   )F)r   )T)%r&   
__future__r   r   r   rk   rC   ru   googlecloudsdk.command_libr   "googlecloudsdk.command_lib.storager   googlecloudsdk.command_lib.utilr   &googlecloudsdk.command_lib.util.anthosr	   googlecloudsdk.corer
   r   r   BinaryBackedOperationr   objectr*   rP   rY   r]   r`   rb   rr   ry   _HASH_CHECK_WARNING_BASErI   r   r   r   r   r   r   r   <module>r      s    '  ' 	   2 5 2 D # * =-CC =:6V :6z,'0O( $ 89 188  4::=I /66}E -r   