1
# Copyright (C) 2003-2007 Robey Pointer <robeypointer@gmail.com>
3
# This file is part of paramiko.
5
# Paramiko is free software; you can redistribute it and/or modify it under the
6
# terms of the GNU Lesser General Public License as published by the Free
7
# Software Foundation; either version 2.1 of the License, or (at your option)
10
# Paramiko is distributed in the hope that it will be useful, but WITHOUT ANY
11
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12
# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
15
# You should have received a copy of the GNU Lesser General Public License
16
# along with Paramiko; if not, write to the Free Software Foundation, Inc.,
17
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
18
from paramiko.common import (
19
linefeed_byte_value, crlf, cr_byte, linefeed_byte, cr_byte_value,
21
from paramiko.py3compat import BytesIO, PY2, u, bytes_types, text_type
23
from paramiko.util import ClosingContextManager
26
class BufferedFile (ClosingContextManager):
28
Reusable base class to implement Python-style file buffering around a
32
_DEFAULT_BUFSIZE = 8192
43
FLAG_LINE_BUFFERED = 0x40
44
FLAG_UNIVERSAL_NEWLINE = 0x80
49
self._bufsize = self._DEFAULT_BUFSIZE
50
self._wbuffer = BytesIO()
51
self._rbuffer = bytes()
52
self._at_trailing_cr = False
54
# pos - position within the file, according to the user
55
# realpos - position according the OS
56
# (these may be different because we buffer for line reading)
57
self._pos = self._realpos = 0
58
# size only matters for seekable files
66
Returns an iterator that can be used to iterate over the lines in this
67
file. This iterator happens to return the file itself, since a file is
70
:raises: ``ValueError`` -- if the file is closed.
73
raise ValueError('I/O operation on closed file')
78
Close the file. Future read and write operations will fail.
85
Write out any data in the write buffer. This may do nothing if write
86
buffering is not turned on.
88
self._write_all(self._wbuffer.getvalue())
89
self._wbuffer = BytesIO()
95
Returns the next line from the input, or raises
96
``StopIteration`` when EOF is hit. Unlike Python file
97
objects, it's okay to mix calls to `next` and `readline`.
99
:raises: ``StopIteration`` -- when the end of the file is reached.
101
:returns: a line (`str`) read from the file.
103
line = self.readline()
110
Returns the next line from the input, or raises ``StopIteration``
111
when EOF is hit. Unlike python file objects, it's okay to mix
112
calls to `.next` and `.readline`.
114
:raises: ``StopIteration`` -- when the end of the file is reached.
116
:returns: a line (`str`) read from the file.
118
line = self.readline()
125
Check if the file can be read from.
128
`True` if the file can be read from. If `False`, `read` will raise
131
return (self._flags & self.FLAG_READ) == self.FLAG_READ
135
Check if the file can be written to.
138
`True` if the file can be written to. If `False`, `write` will
141
return (self._flags & self.FLAG_WRITE) == self.FLAG_WRITE
145
Check if the file supports random access.
148
`True` if the file supports random access. If `False`, `seek` will
153
def readinto(self, buff):
155
Read up to ``len(buff)`` bytes into ``bytearray`` *buff* and return the
156
number of bytes read.
159
The number of bytes read.
161
data = self.read(len(buff))
162
buff[:len(data)] = data
165
def read(self, size=None):
167
Read at most ``size`` bytes from the file (less if we hit the end of
168
the file first). If the ``size`` argument is negative or omitted,
169
read all the remaining data in the file.
172
``'b'`` mode flag is ignored (``self.FLAG_BINARY`` in
173
``self._flags``), because SSH treats all files as binary, since we
174
have no idea what encoding the file is in, or even if the file is
177
:param int size: maximum number of bytes to read
179
data read from the file (as bytes), or an empty string if EOF was
180
encountered immediately
183
raise IOError('File is closed')
184
if not (self._flags & self.FLAG_READ):
185
raise IOError('File is not open for reading')
186
if (size is None) or (size < 0):
188
result = self._rbuffer
189
self._rbuffer = bytes()
190
self._pos += len(result)
193
new_data = self._read(self._DEFAULT_BUFSIZE)
196
if (new_data is None) or (len(new_data) == 0):
199
self._realpos += len(new_data)
200
self._pos += len(new_data)
202
if size <= len(self._rbuffer):
203
result = self._rbuffer[:size]
204
self._rbuffer = self._rbuffer[size:]
205
self._pos += len(result)
207
while len(self._rbuffer) < size:
208
read_size = size - len(self._rbuffer)
209
if self._flags & self.FLAG_BUFFERED:
210
read_size = max(self._bufsize, read_size)
212
new_data = self._read(read_size)
215
if (new_data is None) or (len(new_data) == 0):
217
self._rbuffer += new_data
218
self._realpos += len(new_data)
219
result = self._rbuffer[:size]
220
self._rbuffer = self._rbuffer[size:]
221
self._pos += len(result)
224
def readline(self, size=None):
226
Read one entire line from the file. A trailing newline character is
227
kept in the string (but may be absent when a file ends with an
228
incomplete line). If the size argument is present and non-negative, it
229
is a maximum byte count (including the trailing newline) and an
230
incomplete line may be returned. An empty string is returned only when
231
EOF is encountered immediately.
234
Unlike stdio's ``fgets``, the returned string contains null
235
characters (``'\\0'``) if they occurred in the input.
237
:param int size: maximum length of returned string.
239
next line of the file, or an empty string if the end of the
240
file has been reached.
242
If the file was opened in binary (``'b'``) mode: bytes are returned
243
Else: the encoding of the file is assumed to be UTF-8 and character
244
strings (`str`) are returned
246
# it's almost silly how complex this function is.
248
raise IOError('File is closed')
249
if not (self._flags & self.FLAG_READ):
250
raise IOError('File not open for reading')
255
self._at_trailing_cr and
256
self._flags & self.FLAG_UNIVERSAL_NEWLINE and
259
# edge case: the newline may be '\r\n' and we may have read
260
# only the first '\r' last time.
261
if line[0] == linefeed_byte_value:
263
self._record_newline(crlf)
265
self._record_newline(cr_byte)
266
self._at_trailing_cr = False
267
# check size before looking for a linefeed, in case we already have
269
if (size is not None) and (size >= 0):
270
if len(line) >= size:
272
self._rbuffer = line[size:]
280
linefeed_byte in line or
282
self._flags & self.FLAG_UNIVERSAL_NEWLINE and
288
new_data = self._read(n)
291
if (new_data is None) or (len(new_data) == 0):
292
self._rbuffer = bytes()
293
self._pos += len(line)
294
return line if self._flags & self.FLAG_BINARY else u(line)
296
self._realpos += len(new_data)
298
pos = line.find(linefeed_byte)
299
if self._flags & self.FLAG_UNIVERSAL_NEWLINE:
300
rpos = line.find(cr_byte)
301
if (rpos >= 0) and (rpos < pos or pos < 0):
304
# we couldn't find a newline in the truncated string, return it
305
self._pos += len(line)
306
return line if self._flags & self.FLAG_BINARY else u(line)
309
line[pos] == cr_byte_value and
311
line[xpos] == linefeed_byte_value
314
# if the string was truncated, _rbuffer needs to have the string after
315
# the newline character plus the truncated part of the line we stored
316
# earlier in _rbuffer
318
self._rbuffer = line[xpos:] + self._rbuffer
320
self._rbuffer = line[xpos:]
323
line = line[:pos] + linefeed_byte
324
if (len(self._rbuffer) == 0) and (lf == cr_byte):
325
# we could read the line up to a '\r' and there could still be a
326
# '\n' following that we read next time. note that and eat it.
327
self._at_trailing_cr = True
329
self._record_newline(lf)
330
self._pos += len(line)
331
return line if self._flags & self.FLAG_BINARY else u(line)
333
def readlines(self, sizehint=None):
335
Read all remaining lines using `readline` and return them as a list.
336
If the optional ``sizehint`` argument is present, instead of reading up
337
to EOF, whole lines totalling approximately sizehint bytes (possibly
338
after rounding up to an internal buffer size) are read.
340
:param int sizehint: desired maximum number of bytes to read.
341
:returns: list of lines read from the file.
346
line = self.readline()
350
byte_count += len(line)
351
if (sizehint is not None) and (byte_count >= sizehint):
355
def seek(self, offset, whence=0):
357
Set the file's current position, like stdio's ``fseek``. Not all file
358
objects support seeking.
361
If a file is opened in append mode (``'a'`` or ``'a+'``), any seek
362
operations will be undone at the next write (as the file position
363
will move back to the end of the file).
366
position to move to within the file, relative to ``whence``.
368
type of movement: 0 = absolute; 1 = relative to the current
369
position; 2 = relative to the end of the file.
371
:raises: ``IOError`` -- if the file doesn't support random access.
373
raise IOError('File does not support seeking.')
377
Return the file's current position. This may not be accurate or
378
useful if the underlying file doesn't support random access, or was
379
opened in append mode.
381
:returns: file position (`number <int>` of bytes).
385
def write(self, data):
387
Write data to the file. If write buffering is on (``bufsize`` was
388
specified and non-zero), some or all of the data may not actually be
389
written yet. (Use `flush` or `close` to force buffered data to be
392
:param data: ``str``/``bytes`` data to write
394
if isinstance(data, text_type):
395
# Accept text and encode as utf-8 for compatibility only.
396
data = data.encode('utf-8')
398
raise IOError('File is closed')
399
if not (self._flags & self.FLAG_WRITE):
400
raise IOError('File not open for writing')
401
if not (self._flags & self.FLAG_BUFFERED):
402
self._write_all(data)
404
self._wbuffer.write(data)
405
if self._flags & self.FLAG_LINE_BUFFERED:
406
# only scan the new data for linefeed, to avoid wasting time.
407
last_newline_pos = data.rfind(linefeed_byte)
408
if last_newline_pos >= 0:
409
wbuf = self._wbuffer.getvalue()
410
last_newline_pos += len(wbuf) - len(data)
411
self._write_all(wbuf[:last_newline_pos + 1])
412
self._wbuffer = BytesIO()
413
self._wbuffer.write(wbuf[last_newline_pos + 1:])
415
# even if we're line buffering, if the buffer has grown past the
416
# buffer size, force a flush.
417
if self._wbuffer.tell() >= self._bufsize:
421
def writelines(self, sequence):
423
Write a sequence of strings to the file. The sequence can be any
424
iterable object producing strings, typically a list of strings. (The
425
name is intended to match `readlines`; `writelines` does not add line
428
:param sequence: an iterable sequence of strings.
430
for line in sequence:
434
def xreadlines(self):
436
Identical to ``iter(f)``. This is a deprecated file interface that
437
predates Python iterator support.
447
def _read(self, size):
450
Read data from the stream. Return ``None`` or raise ``EOFError`` to
455
def _write(self, data):
458
Write data into the stream.
460
raise IOError('write not implemented')
465
Return the size of the file. This is called from within `_set_mode`
466
if the file is opened in append mode, so the file position can be
467
tracked and `seek` and `tell` will work correctly. If the file is
468
a stream that can't be randomly accessed, you don't need to override
475
def _set_mode(self, mode='r', bufsize=-1):
477
Subclasses call this method to initialize the BufferedFile.
479
# set bufsize in any event, because it's used for readline().
480
self._bufsize = self._DEFAULT_BUFSIZE
482
# do no buffering by default, because otherwise writes will get
483
# buffered in a way that will probably confuse people.
486
# apparently, line buffering only affects writes. reads are only
487
# buffered if you call readline (directly or indirectly: iterating
488
# over a file will indirectly call readline).
489
self._flags |= self.FLAG_BUFFERED | self.FLAG_LINE_BUFFERED
491
self._bufsize = bufsize
492
self._flags |= self.FLAG_BUFFERED
493
self._flags &= ~self.FLAG_LINE_BUFFERED
496
self._flags &= ~(self.FLAG_BUFFERED | self.FLAG_LINE_BUFFERED)
498
if ('r' in mode) or ('+' in mode):
499
self._flags |= self.FLAG_READ
500
if ('w' in mode) or ('+' in mode):
501
self._flags |= self.FLAG_WRITE
503
self._flags |= self.FLAG_WRITE | self.FLAG_APPEND
504
self._size = self._get_size()
505
self._pos = self._realpos = self._size
507
self._flags |= self.FLAG_BINARY
509
self._flags |= self.FLAG_UNIVERSAL_NEWLINE
510
# built-in file objects have this attribute to store which kinds of
511
# line terminations they've seen:
512
# <http://www.python.org/doc/current/lib/built-in-funcs.html>
515
def _write_all(self, data):
516
# the underlying stream may be something that does partial writes (like
519
count = self._write(data)
521
if self._flags & self.FLAG_APPEND:
523
self._pos = self._realpos = self._size
526
self._realpos += count
529
def _record_newline(self, newline):
530
# silliness about tracking what kinds of newlines we've seen.
531
# i don't understand why it can be None, a string, or a tuple, instead
532
# of just always being a tuple, but we'll emulate that behavior anyway.
533
if not (self._flags & self.FLAG_UNIVERSAL_NEWLINE):
535
if self.newlines is None:
536
self.newlines = newline
538
self.newlines != newline and
539
isinstance(self.newlines, bytes_types)
541
self.newlines = (self.newlines, newline)
542
elif newline not in self.newlines:
543
self.newlines += (newline,)