
    aL                     ^    d dl mZmZmZmZmZ d dlmZmZm	Z	m
Z
mZ d dlmZ  G d de      Zy)    )linefeed_byte_valuecrlfcr_bytelinefeed_bytecr_byte_value)BytesIOPY2ubytes_types	text_type)ClosingContextManagerc                       e Zd ZdZdZdZdZdZdZdZ	dZ
dZdZd	Zd
Zd Zd Zd Zd Zd Zerd Znd Zd Zd Zd Zd Zd&dZd&dZd&dZd'dZd Zd Z d Z!d Z"e#d        Z$d  Z%d! Z&d" Z'd(d#Z(d$ Z)d% Z*y))BufferedFilezc
    Reusable base class to implement Python-style file buffering around a
    simpler stream.
    i    r                   @      c                     d | _         d| _        | j                  | _        t	               | _        t               | _        d| _        d| _	        dx| _
        | _        d| _        y )Nr   F)newlines_flags_DEFAULT_BUFSIZE_bufsizer   _wbufferbytes_rbuffer_at_trailing_cr_closed_pos_realpos_sizeselfs    -lib/python3.12/site-packages/paramiko/file.py__init__zBufferedFile.__init__2   sU    --	$ %&%	DM
    c                 $    | j                          y N)closer$   s    r&   __del__zBufferedFile.__del__A   s    

r(   c                 4    | j                   rt        d      | S )z
        Returns an iterator that can be used to iterate over the lines in this
        file.  This iterator happens to return the file itself, since a file is
        its own iterator.

        :raises: ``ValueError`` -- if the file is closed.
        zI/O operation on closed file)r    
ValueErrorr$   s    r&   __iter__zBufferedFile.__iter__D   s     <<;<<r(   c                 2    | j                          d| _        y)zN
        Close the file.  Future read and write operations will fail.
        TN)flushr    r$   s    r&   r+   zBufferedFile.closeP   s     	

r(   c                 t    | j                  | j                  j                                t               | _        y)z{
        Write out any data in the write buffer.  This may do nothing if write
        buffering is not turned on.
        N)
_write_allr   getvaluer   r$   s    r&   r1   zBufferedFile.flushW   s)    
 	..01	r(   c                 6    | j                         }|st        |S )a\  
            Returns the next line from the input, or raises
            ``StopIteration`` when EOF is hit.  Unlike Python file
            objects, it's okay to mix calls to `next` and `readline`.

            :raises: ``StopIteration`` -- when the end of the file is reached.

            :returns: a line (`str`) read from the file.
            readlineStopIterationr%   lines     r&   nextzBufferedFile.nextb        ==?D##Kr(   c                 6    | j                         }|st        |S )a^  
            Returns the next line from the input, or raises ``StopIteration``
            when EOF is hit.  Unlike python file objects, it's okay to mix
            calls to `.next` and `.readline`.

            :raises: ``StopIteration`` -- when the end of the file is reached.

            :returns: a line (`str`) read from the file.
            r6   r9   s     r&   __next__zBufferedFile.__next__s   r<   r(   c                 N    | j                   | j                  z  | j                  k(  S )z
        Check if the file can be read from.

        :returns:
            `True` if the file can be read from. If `False`, `read` will raise
            an exception.
        )r   	FLAG_READr$   s    r&   readablezBufferedFile.readable   s      dnn,??r(   c                 N    | j                   | j                  z  | j                  k(  S )z
        Check if the file can be written to.

        :returns:
            `True` if the file can be written to. If `False`, `write` will
            raise an exception.
        )r   
FLAG_WRITEr$   s    r&   writablezBufferedFile.writable   s      doo-$//AAr(   c                      y)z
        Check if the file supports random access.

        :returns:
            `True` if the file supports random access. If `False`, `seek` will
            raise an exception.
        F r$   s    r&   seekablezBufferedFile.seekable   s     r(   c                 h    | j                  t        |            }||dt        |       t        |      S )z
        Read up to ``len(buff)`` bytes into ``bytearray`` *buff* and return the
        number of bytes read.

        :returns:
            The number of bytes read.
        N)readlen)r%   buffdatas      r&   readintozBufferedFile.readinto   s0     yyT# [s4y4yr(   Nc                    | j                   rt        d      | j                  | j                  z  st        d      ||dk  r| j                  }t               | _        | xj                  t        |      z  c_        	 	 | j                  | j                        }|t        |      dk(  r	 |S ||z  }| xj                  t        |      z  c_        | xj                  t        |      z  c_        q|t        | j                        k  rC| j                  d| }| j                  |d | _        | xj                  t        |      z  c_        |S t        | j                        |k  r|t        | j                        z
  }| j                  | j                  z  rt        | j                  |      }	 | j                  |      }|t        |      dk(  rnL| xj                  |z  c_        | xj                  t        |      z  c_        t        | j                        |k  r| j                  d| }| j                  |d | _        | xj                  t        |      z  c_        |S # t        $ r d}Y w xY w# t        $ r d}Y w xY w)a  
        Read at most ``size`` bytes from the file (less if we hit the end of
        the file first).  If the ``size`` argument is negative or omitted,
        read all the remaining data in the file.

        .. note::
            ``'b'`` mode flag is ignored (``self.FLAG_BINARY`` in
            ``self._flags``), because SSH treats all files as binary, since we
            have no idea what encoding the file is in, or even if the file is
            text data.

        :param int size: maximum number of bytes to read
        :returns:
            data read from the file (as bytes), or an empty string if EOF was
            encountered immediately
        File is closedzFile is not open for readingNr   )r    IOErrorr   r@   r   r   r!   rJ   _readr   EOFErrorr"   FLAG_BUFFEREDmaxr   )r%   sizeresultnew_data	read_sizes        r&   rI   zBufferedFile.read   s$   " <<*++dnn,899LdQh]]F!GDMIIV$I$#zz$*?*?@H $#h-1*< M ("X.		S]*	  3t}}%%]]5D)F MM$%0DMIIV$IM$-- 4's4==11I{{T///y9	 ::i0  c(mq&8MMX%MMMS]*M $-- 4' u%de,		S[ 	9   $#H$&    s$   >I )I, I)(I),I:9I:c                    | j                   rt        d      | j                  | j                  z  st        d      | j                  }d}	 | j
                  rj| j                  | j                  z  rQt        |      dkD  rC|d   t        k(  r|dd }| j                  t               n| j                  t               d| _        |4|dk\  r/t        |      |k\  r||d | _        |d| }d}n|t        |      z
  }n| j                  }t        |v s!| j                  | j                  z  r	t        |v rn	 | j                  |      }|t        |      dk(  rSt!               | _        | xj"                  t        |      z  c_        | j                  | j$                  z  r|S t'        |      S ||z  }| xj(                  t        |      z  c_        ||j+                  t              }| j                  | j                  z  r&|j+                  t              }|dk\  r||k  s|dk  r|}|dk(  rD| xj"                  t        |      z  c_        | j                  | j$                  z  r|S t'        |      S |dz   }||   t,        k(  r|t        |      k  r||   t        k(  r|dz  }|r||d | j                  z   | _        n
||d | _        ||| }	|d| t        z   }t        | j                        dk(  r|	t        k(  rd| _        n| j                  |	       | xj"                  t        |      z  c_        | j                  | j$                  z  r|S t'        |      S # t        $ r d}Y w xY w)	a  
        Read one entire line from the file.  A trailing newline character is
        kept in the string (but may be absent when a file ends with an
        incomplete line).  If the size argument is present and non-negative, it
        is a maximum byte count (including the trailing newline) and an
        incomplete line may be returned.  An empty string is returned only when
        EOF is encountered immediately.

        .. note::
            Unlike stdio's ``fgets``, the returned string contains null
            characters (``'\0'``) if they occurred in the input.

        :param int size: maximum length of returned string.
        :returns:
            next line of the file, or an empty string if the end of the
            file has been reached.

            If the file was opened in binary (``'b'``) mode: bytes are returned
            Else: the encoding of the file is assumed to be UTF-8 and character
            strings (`str`) are returned
        rO   zFile not open for readingFTr   r   N)r    rP   r   r@   r   r   FLAG_UNIVERSAL_NEWLINErJ   r   _record_newliner   r   r   r   rQ   rR   r   r!   FLAG_BINARYr
   r"   findr   )
r%   rU   r:   	truncatednrW   posrposxposlfs
             r&   r7   zBufferedFile.readline   s   . <<*++dnn,566}}	$$KK$"="==IM 7118D((.((1',$  tqyt9$$(KDM;D $I3t9$MM$d999go ::a=  c(mq&8 %		SY&	#{{T-=-==tJ1T7JHDMMS]*MO R ii&;;44499W%D	s
cAg"9IIT"I;;)9)994FqwFQwI&s4y T
11AID  K$--7DM KDM#d^DSzM)!#"- $(D   $		SY	{{T%5%55tB1T7BU    s   .M MMc                     g }d}	 | j                         }t        |      dk(  r	 |S |j                  |       |t        |      z  }|||k\  r	 |S K)a  
        Read all remaining lines using `readline` and return them as a list.
        If the optional ``sizehint`` argument is present, instead of reading up
        to EOF, whole lines totalling approximately sizehint bytes (possibly
        after rounding up to an internal buffer size) are read.

        :param int sizehint: desired maximum number of bytes to read.
        :returns: list of lines read from the file.
        r   )r7   rJ   append)r%   sizehintlines
byte_countr:   s        r&   	readlineszBufferedFile.readlinesP  sg     
==?D4yA~
 	 LL#d)#J$:+A r(   c                     t        d      )a  
        Set the file's current position, like stdio's ``fseek``.  Not all file
        objects support seeking.

        .. note::
            If a file is opened in append mode (``'a'`` or ``'a+'``), any seek
            operations will be undone at the next write (as the file position
            will move back to the end of the file).

        :param int offset:
            position to move to within the file, relative to ``whence``.
        :param int whence:
            type of movement: 0 = absolute; 1 = relative to the current
            position; 2 = relative to the end of the file.

        :raises: ``IOError`` -- if the file doesn't support random access.
        zFile does not support seeking.rP   )r%   offsetwhences      r&   seekzBufferedFile.seekf  s    $ 677r(   c                     | j                   S )z
        Return the file's current position.  This may not be accurate or
        useful if the underlying file doesn't support random access, or was
        opened in append mode.

        :returns: file position (`number <int>` of bytes).
        )r!   r$   s    r&   tellzBufferedFile.tellz  s     yyr(   c                    t        |t              r|j                  d      }| j                  rt	        d      | j
                  | j                  z  st	        d      | j
                  | j                  z  s| j                  |       y| j                  j                  |       | j
                  | j                  z  r|j                  t              }|dk\  r{| j                  j                         }|t        |      t        |      z
  z  }| j                  |d|dz           t!               | _	        | j                  j                  ||dz   d        y| j                  j#                         | j$                  k\  r| j'                          y)a8  
        Write data to the file.  If write buffering is on (``bufsize`` was
        specified and non-zero), some or all of the data may not actually be
        written yet.  (Use `flush` or `close` to force buffered data to be
        written out.)

        :param data: ``str``/``bytes`` data to write
        zutf-8rO   zFile not open for writingNr   r   )
isinstancer   encoder    rP   r   rC   rS   r3   r   writeFLAG_LINE_BUFFEREDrfindr   r4   rJ   r   rq   r   r1   )r%   rL   last_newline_poswbufs       r&   ru   zBufferedFile.write  s>    dI&;;w'D<<*++doo-566d000OOD!D!;;000#zz-81$}}--/ CID	$99 %;'7!'; <= '	##D)9A)=)?$@A ==4==0JJLr(   c                 4    |D ]  }| j                  |        y)a?  
        Write a sequence of strings to the file.  The sequence can be any
        iterable object producing strings, typically a list of strings.  (The
        name is intended to match `readlines`; `writelines` does not add line
        separators.)

        :param sequence: an iterable sequence of strings.
        N)ru   )r%   sequencer:   s      r&   
writelineszBufferedFile.writelines  s"      	DJJt	r(   c                     | S )z
        Identical to ``iter(f)``.  This is a deprecated file interface that
        predates Python iterator support.
        rF   r$   s    r&   
xreadlineszBufferedFile.xreadlines  s	    
 r(   c                     | j                   S r*   )r    r$   s    r&   closedzBufferedFile.closed  s    ||r(   c                     t               )z
        (subclass override)
        Read data from the stream.  Return ``None`` or raise ``EOFError`` to
        indicate EOF.
        )rR   )r%   rU   s     r&   rQ   zBufferedFile._read  s     jr(   c                     t        d      )zI
        (subclass override)
        Write data into the stream.
        zwrite not implementedrl   )r%   rL   s     r&   _writezBufferedFile._write  s    
 -..r(   c                      y)ai  
        (subclass override)
        Return the size of the file.  This is called from within `_set_mode`
        if the file is opened in append mode, so the file position can be
        tracked and `seek` and `tell` will work correctly.  If the file is
        a stream that can't be randomly accessed, you don't need to override
        this method,
        r   rF   r$   s    r&   	_get_sizezBufferedFile._get_size  s     r(   c                    | j                   | _        |dk  rd}|dk(  r-| xj                  | j                  | j                  z  z  c_        n~|dkD  rG|| _        | xj                  | j                  z  c_        | xj                  | j                   z  c_        n2|dk(  r-| xj                  | j                  | j                  z   z  c_        d|v sd|v r| xj                  | j
                  z  c_        d|v sd|v r| xj                  | j                  z  c_        d|v rY| xj                  | j                  | j                  z  z  c_        | j                         | _	        | j                  x| _
        | _        d|v r| xj                  | j                  z  c_        d|v r'| xj                  | j                  z  c_        d	| _        y	y	)
zM
        Subclasses call this method to initialize the BufferedFile.
        r   r   r+wabUN)r   r   r   rS   rv   r@   rC   FLAG_APPENDr   r#   r!   r"   r]   r[   r   )r%   modebufsizes      r&   	_set_modezBufferedFile._set_mode  so   
 --Q; Ga< KK4--0G0GGGKq[#DMKK4---KKKD3333K\KKT//$2I2IIJJK4KSD[KK4>>)K4KSD[KK4??*K$;KK4??T-=-===K)DJ(,

2DI$;KK4+++K$;KK4666K !DM r(   c                 L   t        |      dkD  r| j                  |      }||d  }| j                  | j                  z  r.| xj                  |z  c_        | j                  x| _        | _        n*| xj
                  |z  c_        | xj                  |z  c_        t        |      dkD  ry )Nr   )rJ   r   r   r   r#   r!   r"   )r%   rL   counts      r&   r3   zBufferedFile._write_all  s     $i!mKK%E<D{{T---

e#
,0JJ6	DM		U"	& $i!m r(   c                 $   | j                   | j                  z  sy | j                  || _        y | j                  |k7  r.t        | j                  t              r| j                  |f| _        y || j                  vr| xj                  |fz  c_        y y r*   )r   r[   r   rs   r   )r%   newlines     r&   r\   zBufferedFile._record_newline  sy     d999== #DM]]g%*MM;+
 "]]G4DMDMM)MMgZ'M *r(   r*   )r   )r   rZ   )+__name__
__module____qualname____doc__r   SEEK_SETSEEK_CURSEEK_ENDr@   rC   r   r]   rS   rv   r[   r'   r,   r/   r+   r1   r	   r;   r>   rA   rD   rG   rM   rI   r7   rj   ro   rq   ru   r|   r~   propertyr   rQ   r   r   r   r3   r\   rF   r(   r&   r   r      s    
 HHHIJKKM!
 	"	@B
9vgCR,8("H  
/	&!P(r(   r   N)paramiko.commonr   r   r   r   r   paramiko.py3compatr   r	   r
   r   r   paramiko.utilr   r   rF   r(   r&   <module>r      s*   $  G F /C(( C(r(   