1 /*
2     An implementation of Buffered I/O as defined by PEP 3116 - "New I/O"
3 
4     Classes defined here: BufferedIOBase, BufferedReader, BufferedWriter,
5     BufferedRandom.
6 
7     Written by Amaury Forgeot d'Arc and Antoine Pitrou
8 */
9 
10 #define PY_SSIZE_T_CLEAN
11 #include "Python.h"
12 #include "pycore_call.h"          // _PyObject_CallNoArgs()
13 #include "pycore_object.h"
14 #include "structmember.h"         // PyMemberDef
15 #include "_iomodule.h"
16 
17 /*[clinic input]
18 module _io
19 class _io._BufferedIOBase "PyObject *" "&PyBufferedIOBase_Type"
20 class _io._Buffered "buffered *" "&PyBufferedIOBase_Type"
21 class _io.BufferedReader "buffered *" "&PyBufferedReader_Type"
22 class _io.BufferedWriter "buffered *" "&PyBufferedWriter_Type"
23 class _io.BufferedRWPair "rwpair *" "&PyBufferedRWPair_Type"
24 class _io.BufferedRandom "buffered *" "&PyBufferedRandom_Type"
25 [clinic start generated code]*/
26 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=59460b9c5639984d]*/
27 
28 _Py_IDENTIFIER(close);
29 _Py_IDENTIFIER(_dealloc_warn);
30 _Py_IDENTIFIER(flush);
31 _Py_IDENTIFIER(isatty);
32 _Py_IDENTIFIER(mode);
33 _Py_IDENTIFIER(name);
34 _Py_IDENTIFIER(peek);
35 _Py_IDENTIFIER(read);
36 _Py_IDENTIFIER(read1);
37 _Py_IDENTIFIER(readable);
38 _Py_IDENTIFIER(readinto);
39 _Py_IDENTIFIER(readinto1);
40 _Py_IDENTIFIER(writable);
41 _Py_IDENTIFIER(write);
42 
43 /*
44  * BufferedIOBase class, inherits from IOBase.
45  */
46 PyDoc_STRVAR(bufferediobase_doc,
47     "Base class for buffered IO objects.\n"
48     "\n"
49     "The main difference with RawIOBase is that the read() method\n"
50     "supports omitting the size argument, and does not have a default\n"
51     "implementation that defers to readinto().\n"
52     "\n"
53     "In addition, read(), readinto() and write() may raise\n"
54     "BlockingIOError if the underlying raw stream is in non-blocking\n"
55     "mode and not ready; unlike their raw counterparts, they will never\n"
56     "return None.\n"
57     "\n"
58     "A typical implementation should not inherit from a RawIOBase\n"
59     "implementation, but wrap one.\n"
60     );
61 
62 static PyObject *
_bufferediobase_readinto_generic(PyObject * self,Py_buffer * buffer,char readinto1)63 _bufferediobase_readinto_generic(PyObject *self, Py_buffer *buffer, char readinto1)
64 {
65     Py_ssize_t len;
66     PyObject *data;
67 
68     data = _PyObject_CallMethodId(self,
69                                   readinto1 ? &PyId_read1 : &PyId_read,
70                                   "n", buffer->len);
71     if (data == NULL)
72         return NULL;
73 
74     if (!PyBytes_Check(data)) {
75         Py_DECREF(data);
76         PyErr_SetString(PyExc_TypeError, "read() should return bytes");
77         return NULL;
78     }
79 
80     len = PyBytes_GET_SIZE(data);
81     if (len > buffer->len) {
82         PyErr_Format(PyExc_ValueError,
83                      "read() returned too much data: "
84                      "%zd bytes requested, %zd returned",
85                      buffer->len, len);
86         Py_DECREF(data);
87         return NULL;
88     }
89     memcpy(buffer->buf, PyBytes_AS_STRING(data), len);
90 
91     Py_DECREF(data);
92 
93     return PyLong_FromSsize_t(len);
94 }
95 
96 /*[clinic input]
97 _io._BufferedIOBase.readinto
98     buffer: Py_buffer(accept={rwbuffer})
99     /
100 [clinic start generated code]*/
101 
102 static PyObject *
_io__BufferedIOBase_readinto_impl(PyObject * self,Py_buffer * buffer)103 _io__BufferedIOBase_readinto_impl(PyObject *self, Py_buffer *buffer)
104 /*[clinic end generated code: output=8c8cda6684af8038 input=00a6b9a38f29830a]*/
105 {
106     return _bufferediobase_readinto_generic(self, buffer, 0);
107 }
108 
109 /*[clinic input]
110 _io._BufferedIOBase.readinto1
111     buffer: Py_buffer(accept={rwbuffer})
112     /
113 [clinic start generated code]*/
114 
115 static PyObject *
_io__BufferedIOBase_readinto1_impl(PyObject * self,Py_buffer * buffer)116 _io__BufferedIOBase_readinto1_impl(PyObject *self, Py_buffer *buffer)
117 /*[clinic end generated code: output=358623e4fd2b69d3 input=ebad75b4aadfb9be]*/
118 {
119     return _bufferediobase_readinto_generic(self, buffer, 1);
120 }
121 
122 static PyObject *
bufferediobase_unsupported(const char * message)123 bufferediobase_unsupported(const char *message)
124 {
125     _PyIO_State *state = IO_STATE();
126     if (state != NULL)
127         PyErr_SetString(state->unsupported_operation, message);
128     return NULL;
129 }
130 
131 /*[clinic input]
132 _io._BufferedIOBase.detach
133 
134 Disconnect this buffer from its underlying raw stream and return it.
135 
136 After the raw stream has been detached, the buffer is in an unusable
137 state.
138 [clinic start generated code]*/
139 
140 static PyObject *
_io__BufferedIOBase_detach_impl(PyObject * self)141 _io__BufferedIOBase_detach_impl(PyObject *self)
142 /*[clinic end generated code: output=754977c8d10ed88c input=822427fb58fe4169]*/
143 {
144     return bufferediobase_unsupported("detach");
145 }
146 
147 PyDoc_STRVAR(bufferediobase_read_doc,
148     "Read and return up to n bytes.\n"
149     "\n"
150     "If the argument is omitted, None, or negative, reads and\n"
151     "returns all data until EOF.\n"
152     "\n"
153     "If the argument is positive, and the underlying raw stream is\n"
154     "not 'interactive', multiple raw reads may be issued to satisfy\n"
155     "the byte count (unless EOF is reached first).  But for\n"
156     "interactive raw streams (as well as sockets and pipes), at most\n"
157     "one raw read will be issued, and a short result does not imply\n"
158     "that EOF is imminent.\n"
159     "\n"
160     "Returns an empty bytes object on EOF.\n"
161     "\n"
162     "Returns None if the underlying raw stream was open in non-blocking\n"
163     "mode and no data is available at the moment.\n");
164 
165 static PyObject *
bufferediobase_read(PyObject * self,PyObject * args)166 bufferediobase_read(PyObject *self, PyObject *args)
167 {
168     return bufferediobase_unsupported("read");
169 }
170 
171 PyDoc_STRVAR(bufferediobase_read1_doc,
172     "Read and return up to n bytes, with at most one read() call\n"
173     "to the underlying raw stream. A short result does not imply\n"
174     "that EOF is imminent.\n"
175     "\n"
176     "Returns an empty bytes object on EOF.\n");
177 
178 static PyObject *
bufferediobase_read1(PyObject * self,PyObject * args)179 bufferediobase_read1(PyObject *self, PyObject *args)
180 {
181     return bufferediobase_unsupported("read1");
182 }
183 
184 PyDoc_STRVAR(bufferediobase_write_doc,
185     "Write the given buffer to the IO stream.\n"
186     "\n"
187     "Returns the number of bytes written, which is always the length of b\n"
188     "in bytes.\n"
189     "\n"
190     "Raises BlockingIOError if the buffer is full and the\n"
191     "underlying raw stream cannot accept more data at the moment.\n");
192 
193 static PyObject *
bufferediobase_write(PyObject * self,PyObject * args)194 bufferediobase_write(PyObject *self, PyObject *args)
195 {
196     return bufferediobase_unsupported("write");
197 }
198 
199 
200 typedef struct {
201     PyObject_HEAD
202 
203     PyObject *raw;
204     int ok;    /* Initialized? */
205     int detached;
206     int readable;
207     int writable;
208     char finalizing;
209 
210     /* True if this is a vanilla Buffered object (rather than a user derived
211        class) *and* the raw stream is a vanilla FileIO object. */
212     int fast_closed_checks;
213 
214     /* Absolute position inside the raw stream (-1 if unknown). */
215     Py_off_t abs_pos;
216 
217     /* A static buffer of size `buffer_size` */
218     char *buffer;
219     /* Current logical position in the buffer. */
220     Py_off_t pos;
221     /* Position of the raw stream in the buffer. */
222     Py_off_t raw_pos;
223 
224     /* Just after the last buffered byte in the buffer, or -1 if the buffer
225        isn't ready for reading. */
226     Py_off_t read_end;
227 
228     /* Just after the last byte actually written */
229     Py_off_t write_pos;
230     /* Just after the last byte waiting to be written, or -1 if the buffer
231        isn't ready for writing. */
232     Py_off_t write_end;
233 
234     PyThread_type_lock lock;
235     volatile unsigned long owner;
236 
237     Py_ssize_t buffer_size;
238     Py_ssize_t buffer_mask;
239 
240     PyObject *dict;
241     PyObject *weakreflist;
242 } buffered;
243 
244 /*
245     Implementation notes:
246 
247     * BufferedReader, BufferedWriter and BufferedRandom try to share most
248       methods (this is helped by the members `readable` and `writable`, which
249       are initialized in the respective constructors)
250     * They also share a single buffer for reading and writing. This enables
251       interleaved reads and writes without flushing. It also makes the logic
252       a bit trickier to get right.
253     * The absolute position of the raw stream is cached, if possible, in the
254       `abs_pos` member. It must be updated every time an operation is done
255       on the raw stream. If not sure, it can be reinitialized by calling
256       _buffered_raw_tell(), which queries the raw stream (_buffered_raw_seek()
257       also does it). To read it, use RAW_TELL().
258     * Three helpers, _bufferedreader_raw_read, _bufferedwriter_raw_write and
259       _bufferedwriter_flush_unlocked do a lot of useful housekeeping.
260 
261     NOTE: we should try to maintain block alignment of reads and writes to the
262     raw stream (according to the buffer size), but for now it is only done
263     in read() and friends.
264 
265 */
266 
267 /* These macros protect the buffered object against concurrent operations. */
268 
269 static int
_enter_buffered_busy(buffered * self)270 _enter_buffered_busy(buffered *self)
271 {
272     int relax_locking;
273     PyLockStatus st;
274     if (self->owner == PyThread_get_thread_ident()) {
275         PyErr_Format(PyExc_RuntimeError,
276                      "reentrant call inside %R", self);
277         return 0;
278     }
279     relax_locking = _Py_IsFinalizing();
280     Py_BEGIN_ALLOW_THREADS
281     if (!relax_locking)
282         st = PyThread_acquire_lock(self->lock, 1);
283     else {
284         /* When finalizing, we don't want a deadlock to happen with daemon
285          * threads abruptly shut down while they owned the lock.
286          * Therefore, only wait for a grace period (1 s.).
287          * Note that non-daemon threads have already exited here, so this
288          * shouldn't affect carefully written threaded I/O code.
289          */
290         st = PyThread_acquire_lock_timed(self->lock, (PY_TIMEOUT_T)1e6, 0);
291     }
292     Py_END_ALLOW_THREADS
293     if (relax_locking && st != PY_LOCK_ACQUIRED) {
294         PyObject *ascii = PyObject_ASCII((PyObject*)self);
295         _Py_FatalErrorFormat(__func__,
296             "could not acquire lock for %s at interpreter "
297             "shutdown, possibly due to daemon threads",
298             ascii ? PyUnicode_AsUTF8(ascii) : "<ascii(self) failed>");
299     }
300     return 1;
301 }
302 
303 #define ENTER_BUFFERED(self) \
304     ( (PyThread_acquire_lock(self->lock, 0) ? \
305        1 : _enter_buffered_busy(self)) \
306      && (self->owner = PyThread_get_thread_ident(), 1) )
307 
308 #define LEAVE_BUFFERED(self) \
309     do { \
310         self->owner = 0; \
311         PyThread_release_lock(self->lock); \
312     } while(0);
313 
314 #define CHECK_INITIALIZED(self) \
315     if (self->ok <= 0) { \
316         if (self->detached) { \
317             PyErr_SetString(PyExc_ValueError, \
318                  "raw stream has been detached"); \
319         } else { \
320             PyErr_SetString(PyExc_ValueError, \
321                 "I/O operation on uninitialized object"); \
322         } \
323         return NULL; \
324     }
325 
326 #define CHECK_INITIALIZED_INT(self) \
327     if (self->ok <= 0) { \
328         if (self->detached) { \
329             PyErr_SetString(PyExc_ValueError, \
330                  "raw stream has been detached"); \
331         } else { \
332             PyErr_SetString(PyExc_ValueError, \
333                 "I/O operation on uninitialized object"); \
334         } \
335         return -1; \
336     }
337 
338 #define IS_CLOSED(self) \
339     (!self->buffer || \
340     (self->fast_closed_checks \
341      ? _PyFileIO_closed(self->raw) \
342      : buffered_closed(self)))
343 
344 #define CHECK_CLOSED(self, error_msg) \
345     if (IS_CLOSED(self) & (Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t) == 0)) { \
346         PyErr_SetString(PyExc_ValueError, error_msg); \
347         return NULL; \
348     } \
349 
350 #define VALID_READ_BUFFER(self) \
351     (self->readable && self->read_end != -1)
352 
353 #define VALID_WRITE_BUFFER(self) \
354     (self->writable && self->write_end != -1)
355 
356 #define ADJUST_POSITION(self, _new_pos) \
357     do { \
358         self->pos = _new_pos; \
359         if (VALID_READ_BUFFER(self) && self->read_end < self->pos) \
360             self->read_end = self->pos; \
361     } while(0)
362 
363 #define READAHEAD(self) \
364     ((self->readable && VALID_READ_BUFFER(self)) \
365         ? (self->read_end - self->pos) : 0)
366 
367 #define RAW_OFFSET(self) \
368     (((VALID_READ_BUFFER(self) || VALID_WRITE_BUFFER(self)) \
369         && self->raw_pos >= 0) ? self->raw_pos - self->pos : 0)
370 
371 #define RAW_TELL(self) \
372     (self->abs_pos != -1 ? self->abs_pos : _buffered_raw_tell(self))
373 
374 #define MINUS_LAST_BLOCK(self, size) \
375     (self->buffer_mask ? \
376         (size & ~self->buffer_mask) : \
377         (self->buffer_size * (size / self->buffer_size)))
378 
379 
380 static void
buffered_dealloc(buffered * self)381 buffered_dealloc(buffered *self)
382 {
383     self->finalizing = 1;
384     if (_PyIOBase_finalize((PyObject *) self) < 0)
385         return;
386     _PyObject_GC_UNTRACK(self);
387     self->ok = 0;
388     if (self->weakreflist != NULL)
389         PyObject_ClearWeakRefs((PyObject *)self);
390     Py_CLEAR(self->raw);
391     if (self->buffer) {
392         PyMem_Free(self->buffer);
393         self->buffer = NULL;
394     }
395     if (self->lock) {
396         PyThread_free_lock(self->lock);
397         self->lock = NULL;
398     }
399     Py_CLEAR(self->dict);
400     Py_TYPE(self)->tp_free((PyObject *)self);
401 }
402 
403 static PyObject *
buffered_sizeof(buffered * self,PyObject * Py_UNUSED (ignored))404 buffered_sizeof(buffered *self, PyObject *Py_UNUSED(ignored))
405 {
406     Py_ssize_t res;
407 
408     res = _PyObject_SIZE(Py_TYPE(self));
409     if (self->buffer)
410         res += self->buffer_size;
411     return PyLong_FromSsize_t(res);
412 }
413 
414 static int
buffered_traverse(buffered * self,visitproc visit,void * arg)415 buffered_traverse(buffered *self, visitproc visit, void *arg)
416 {
417     Py_VISIT(self->raw);
418     Py_VISIT(self->dict);
419     return 0;
420 }
421 
422 static int
buffered_clear(buffered * self)423 buffered_clear(buffered *self)
424 {
425     self->ok = 0;
426     Py_CLEAR(self->raw);
427     Py_CLEAR(self->dict);
428     return 0;
429 }
430 
431 /* Because this can call arbitrary code, it shouldn't be called when
432    the refcount is 0 (that is, not directly from tp_dealloc unless
433    the refcount has been temporarily re-incremented). */
434 static PyObject *
buffered_dealloc_warn(buffered * self,PyObject * source)435 buffered_dealloc_warn(buffered *self, PyObject *source)
436 {
437     if (self->ok && self->raw) {
438         PyObject *r;
439         r = _PyObject_CallMethodIdOneArg(self->raw, &PyId__dealloc_warn,
440                                          source);
441         if (r)
442             Py_DECREF(r);
443         else
444             PyErr_Clear();
445     }
446     Py_RETURN_NONE;
447 }
448 
449 /*
450  * _BufferedIOMixin methods
451  * This is not a class, just a collection of methods that will be reused
452  * by BufferedReader and BufferedWriter
453  */
454 
455 /* Flush and close */
456 
457 static PyObject *
buffered_simple_flush(buffered * self,PyObject * args)458 buffered_simple_flush(buffered *self, PyObject *args)
459 {
460     CHECK_INITIALIZED(self)
461     return PyObject_CallMethodNoArgs(self->raw, _PyIO_str_flush);
462 }
463 
464 static int
buffered_closed(buffered * self)465 buffered_closed(buffered *self)
466 {
467     int closed;
468     PyObject *res;
469     CHECK_INITIALIZED_INT(self)
470     res = PyObject_GetAttr(self->raw, _PyIO_str_closed);
471     if (res == NULL)
472         return -1;
473     closed = PyObject_IsTrue(res);
474     Py_DECREF(res);
475     return closed;
476 }
477 
478 static PyObject *
buffered_closed_get(buffered * self,void * context)479 buffered_closed_get(buffered *self, void *context)
480 {
481     CHECK_INITIALIZED(self)
482     return PyObject_GetAttr(self->raw, _PyIO_str_closed);
483 }
484 
485 static PyObject *
buffered_close(buffered * self,PyObject * args)486 buffered_close(buffered *self, PyObject *args)
487 {
488     PyObject *res = NULL, *exc = NULL, *val, *tb;
489     int r;
490 
491     CHECK_INITIALIZED(self)
492     if (!ENTER_BUFFERED(self))
493         return NULL;
494 
495     r = buffered_closed(self);
496     if (r < 0)
497         goto end;
498     if (r > 0) {
499         res = Py_None;
500         Py_INCREF(res);
501         goto end;
502     }
503 
504     if (self->finalizing) {
505         PyObject *r = buffered_dealloc_warn(self, (PyObject *) self);
506         if (r)
507             Py_DECREF(r);
508         else
509             PyErr_Clear();
510     }
511     /* flush() will most probably re-take the lock, so drop it first */
512     LEAVE_BUFFERED(self)
513     res = PyObject_CallMethodNoArgs((PyObject *)self, _PyIO_str_flush);
514     if (!ENTER_BUFFERED(self))
515         return NULL;
516     if (res == NULL)
517         PyErr_Fetch(&exc, &val, &tb);
518     else
519         Py_DECREF(res);
520 
521     res = PyObject_CallMethodNoArgs(self->raw, _PyIO_str_close);
522 
523     if (self->buffer) {
524         PyMem_Free(self->buffer);
525         self->buffer = NULL;
526     }
527 
528     if (exc != NULL) {
529         _PyErr_ChainExceptions(exc, val, tb);
530         Py_CLEAR(res);
531     }
532 
533     self->read_end = 0;
534     self->pos = 0;
535 
536 end:
537     LEAVE_BUFFERED(self)
538     return res;
539 }
540 
541 /* detach */
542 
543 static PyObject *
buffered_detach(buffered * self,PyObject * Py_UNUSED (ignored))544 buffered_detach(buffered *self, PyObject *Py_UNUSED(ignored))
545 {
546     PyObject *raw, *res;
547     CHECK_INITIALIZED(self)
548     res = PyObject_CallMethodNoArgs((PyObject *)self, _PyIO_str_flush);
549     if (res == NULL)
550         return NULL;
551     Py_DECREF(res);
552     raw = self->raw;
553     self->raw = NULL;
554     self->detached = 1;
555     self->ok = 0;
556     return raw;
557 }
558 
559 /* Inquiries */
560 
561 static PyObject *
buffered_seekable(buffered * self,PyObject * Py_UNUSED (ignored))562 buffered_seekable(buffered *self, PyObject *Py_UNUSED(ignored))
563 {
564     CHECK_INITIALIZED(self)
565     return PyObject_CallMethodNoArgs(self->raw, _PyIO_str_seekable);
566 }
567 
568 static PyObject *
buffered_readable(buffered * self,PyObject * Py_UNUSED (ignored))569 buffered_readable(buffered *self, PyObject *Py_UNUSED(ignored))
570 {
571     CHECK_INITIALIZED(self)
572     return PyObject_CallMethodNoArgs(self->raw, _PyIO_str_readable);
573 }
574 
575 static PyObject *
buffered_writable(buffered * self,PyObject * Py_UNUSED (ignored))576 buffered_writable(buffered *self, PyObject *Py_UNUSED(ignored))
577 {
578     CHECK_INITIALIZED(self)
579     return PyObject_CallMethodNoArgs(self->raw, _PyIO_str_writable);
580 }
581 
582 static PyObject *
buffered_name_get(buffered * self,void * context)583 buffered_name_get(buffered *self, void *context)
584 {
585     CHECK_INITIALIZED(self)
586     return _PyObject_GetAttrId(self->raw, &PyId_name);
587 }
588 
589 static PyObject *
buffered_mode_get(buffered * self,void * context)590 buffered_mode_get(buffered *self, void *context)
591 {
592     CHECK_INITIALIZED(self)
593     return _PyObject_GetAttrId(self->raw, &PyId_mode);
594 }
595 
596 /* Lower-level APIs */
597 
598 static PyObject *
buffered_fileno(buffered * self,PyObject * Py_UNUSED (ignored))599 buffered_fileno(buffered *self, PyObject *Py_UNUSED(ignored))
600 {
601     CHECK_INITIALIZED(self)
602     return PyObject_CallMethodNoArgs(self->raw, _PyIO_str_fileno);
603 }
604 
605 static PyObject *
buffered_isatty(buffered * self,PyObject * Py_UNUSED (ignored))606 buffered_isatty(buffered *self, PyObject *Py_UNUSED(ignored))
607 {
608     CHECK_INITIALIZED(self)
609     return PyObject_CallMethodNoArgs(self->raw, _PyIO_str_isatty);
610 }
611 
612 /* Forward decls */
613 static PyObject *
614 _bufferedwriter_flush_unlocked(buffered *);
615 static Py_ssize_t
616 _bufferedreader_fill_buffer(buffered *self);
617 static void
618 _bufferedreader_reset_buf(buffered *self);
619 static void
620 _bufferedwriter_reset_buf(buffered *self);
621 static PyObject *
622 _bufferedreader_peek_unlocked(buffered *self);
623 static PyObject *
624 _bufferedreader_read_all(buffered *self);
625 static PyObject *
626 _bufferedreader_read_fast(buffered *self, Py_ssize_t);
627 static PyObject *
628 _bufferedreader_read_generic(buffered *self, Py_ssize_t);
629 static Py_ssize_t
630 _bufferedreader_raw_read(buffered *self, char *start, Py_ssize_t len);
631 
632 /*
633  * Helpers
634  */
635 
636 /* Sets the current error to BlockingIOError */
637 static void
_set_BlockingIOError(const char * msg,Py_ssize_t written)638 _set_BlockingIOError(const char *msg, Py_ssize_t written)
639 {
640     PyObject *err;
641     PyErr_Clear();
642     err = PyObject_CallFunction(PyExc_BlockingIOError, "isn",
643                                 errno, msg, written);
644     if (err)
645         PyErr_SetObject(PyExc_BlockingIOError, err);
646     Py_XDECREF(err);
647 }
648 
649 /* Returns the address of the `written` member if a BlockingIOError was
650    raised, NULL otherwise. The error is always re-raised. */
651 static Py_ssize_t *
_buffered_check_blocking_error(void)652 _buffered_check_blocking_error(void)
653 {
654     PyObject *t, *v, *tb;
655     PyOSErrorObject *err;
656 
657     PyErr_Fetch(&t, &v, &tb);
658     if (v == NULL || !PyErr_GivenExceptionMatches(v, PyExc_BlockingIOError)) {
659         PyErr_Restore(t, v, tb);
660         return NULL;
661     }
662     err = (PyOSErrorObject *) v;
663     /* TODO: sanity check (err->written >= 0) */
664     PyErr_Restore(t, v, tb);
665     return &err->written;
666 }
667 
668 static Py_off_t
_buffered_raw_tell(buffered * self)669 _buffered_raw_tell(buffered *self)
670 {
671     Py_off_t n;
672     PyObject *res;
673     res = PyObject_CallMethodNoArgs(self->raw, _PyIO_str_tell);
674     if (res == NULL)
675         return -1;
676     n = PyNumber_AsOff_t(res, PyExc_ValueError);
677     Py_DECREF(res);
678     if (n < 0) {
679         if (!PyErr_Occurred())
680             PyErr_Format(PyExc_OSError,
681                          "Raw stream returned invalid position %" PY_PRIdOFF,
682                          (PY_OFF_T_COMPAT)n);
683         return -1;
684     }
685     self->abs_pos = n;
686     return n;
687 }
688 
689 static Py_off_t
_buffered_raw_seek(buffered * self,Py_off_t target,int whence)690 _buffered_raw_seek(buffered *self, Py_off_t target, int whence)
691 {
692     PyObject *res, *posobj, *whenceobj;
693     Py_off_t n;
694 
695     posobj = PyLong_FromOff_t(target);
696     if (posobj == NULL)
697         return -1;
698     whenceobj = PyLong_FromLong(whence);
699     if (whenceobj == NULL) {
700         Py_DECREF(posobj);
701         return -1;
702     }
703     res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_seek,
704                                      posobj, whenceobj, NULL);
705     Py_DECREF(posobj);
706     Py_DECREF(whenceobj);
707     if (res == NULL)
708         return -1;
709     n = PyNumber_AsOff_t(res, PyExc_ValueError);
710     Py_DECREF(res);
711     if (n < 0) {
712         if (!PyErr_Occurred())
713             PyErr_Format(PyExc_OSError,
714                          "Raw stream returned invalid position %" PY_PRIdOFF,
715                          (PY_OFF_T_COMPAT)n);
716         return -1;
717     }
718     self->abs_pos = n;
719     return n;
720 }
721 
722 static int
_buffered_init(buffered * self)723 _buffered_init(buffered *self)
724 {
725     Py_ssize_t n;
726     if (self->buffer_size <= 0) {
727         PyErr_SetString(PyExc_ValueError,
728             "buffer size must be strictly positive");
729         return -1;
730     }
731     if (self->buffer)
732         PyMem_Free(self->buffer);
733     self->buffer = PyMem_Malloc(self->buffer_size);
734     if (self->buffer == NULL) {
735         PyErr_NoMemory();
736         return -1;
737     }
738     if (self->lock)
739         PyThread_free_lock(self->lock);
740     self->lock = PyThread_allocate_lock();
741     if (self->lock == NULL) {
742         PyErr_SetString(PyExc_RuntimeError, "can't allocate read lock");
743         return -1;
744     }
745     self->owner = 0;
746     /* Find out whether buffer_size is a power of 2 */
747     /* XXX is this optimization useful? */
748     for (n = self->buffer_size - 1; n & 1; n >>= 1)
749         ;
750     if (n == 0)
751         self->buffer_mask = self->buffer_size - 1;
752     else
753         self->buffer_mask = 0;
754     if (_buffered_raw_tell(self) == -1)
755         PyErr_Clear();
756     return 0;
757 }
758 
759 /* Return 1 if an OSError with errno == EINTR is set (and then
760    clears the error indicator), 0 otherwise.
761    Should only be called when PyErr_Occurred() is true.
762 */
763 int
_PyIO_trap_eintr(void)764 _PyIO_trap_eintr(void)
765 {
766     static PyObject *eintr_int = NULL;
767     PyObject *typ, *val, *tb;
768     PyOSErrorObject *env_err;
769 
770     if (eintr_int == NULL) {
771         eintr_int = PyLong_FromLong(EINTR);
772         assert(eintr_int != NULL);
773     }
774     if (!PyErr_ExceptionMatches(PyExc_OSError))
775         return 0;
776     PyErr_Fetch(&typ, &val, &tb);
777     PyErr_NormalizeException(&typ, &val, &tb);
778     env_err = (PyOSErrorObject *) val;
779     assert(env_err != NULL);
780     if (env_err->myerrno != NULL &&
781         PyObject_RichCompareBool(env_err->myerrno, eintr_int, Py_EQ) > 0) {
782         Py_DECREF(typ);
783         Py_DECREF(val);
784         Py_XDECREF(tb);
785         return 1;
786     }
787     /* This silences any error set by PyObject_RichCompareBool() */
788     PyErr_Restore(typ, val, tb);
789     return 0;
790 }
791 
792 /*
793  * Shared methods and wrappers
794  */
795 
796 static PyObject *
buffered_flush_and_rewind_unlocked(buffered * self)797 buffered_flush_and_rewind_unlocked(buffered *self)
798 {
799     PyObject *res;
800 
801     res = _bufferedwriter_flush_unlocked(self);
802     if (res == NULL)
803         return NULL;
804     Py_DECREF(res);
805 
806     if (self->readable) {
807         /* Rewind the raw stream so that its position corresponds to
808            the current logical position. */
809         Py_off_t n;
810         n = _buffered_raw_seek(self, -RAW_OFFSET(self), 1);
811         _bufferedreader_reset_buf(self);
812         if (n == -1)
813             return NULL;
814     }
815     Py_RETURN_NONE;
816 }
817 
818 static PyObject *
buffered_flush(buffered * self,PyObject * args)819 buffered_flush(buffered *self, PyObject *args)
820 {
821     PyObject *res;
822 
823     CHECK_INITIALIZED(self)
824     CHECK_CLOSED(self, "flush of closed file")
825 
826     if (!ENTER_BUFFERED(self))
827         return NULL;
828     res = buffered_flush_and_rewind_unlocked(self);
829     LEAVE_BUFFERED(self)
830 
831     return res;
832 }
833 
834 /*[clinic input]
835 _io._Buffered.peek
836     size: Py_ssize_t = 0
837     /
838 
839 [clinic start generated code]*/
840 
841 static PyObject *
_io__Buffered_peek_impl(buffered * self,Py_ssize_t size)842 _io__Buffered_peek_impl(buffered *self, Py_ssize_t size)
843 /*[clinic end generated code: output=ba7a097ca230102b input=37ffb97d06ff4adb]*/
844 {
845     PyObject *res = NULL;
846 
847     CHECK_INITIALIZED(self)
848     CHECK_CLOSED(self, "peek of closed file")
849 
850     if (!ENTER_BUFFERED(self))
851         return NULL;
852 
853     if (self->writable) {
854         res = buffered_flush_and_rewind_unlocked(self);
855         if (res == NULL)
856             goto end;
857         Py_CLEAR(res);
858     }
859     res = _bufferedreader_peek_unlocked(self);
860 
861 end:
862     LEAVE_BUFFERED(self)
863     return res;
864 }
865 
866 /*[clinic input]
867 _io._Buffered.read
868     size as n: Py_ssize_t(accept={int, NoneType}) = -1
869     /
870 [clinic start generated code]*/
871 
872 static PyObject *
_io__Buffered_read_impl(buffered * self,Py_ssize_t n)873 _io__Buffered_read_impl(buffered *self, Py_ssize_t n)
874 /*[clinic end generated code: output=f41c78bb15b9bbe9 input=7df81e82e08a68a2]*/
875 {
876     PyObject *res;
877 
878     CHECK_INITIALIZED(self)
879     if (n < -1) {
880         PyErr_SetString(PyExc_ValueError,
881                         "read length must be non-negative or -1");
882         return NULL;
883     }
884 
885     CHECK_CLOSED(self, "read of closed file")
886 
887     if (n == -1) {
888         /* The number of bytes is unspecified, read until the end of stream */
889         if (!ENTER_BUFFERED(self))
890             return NULL;
891         res = _bufferedreader_read_all(self);
892     }
893     else {
894         res = _bufferedreader_read_fast(self, n);
895         if (res != Py_None)
896             return res;
897         Py_DECREF(res);
898         if (!ENTER_BUFFERED(self))
899             return NULL;
900         res = _bufferedreader_read_generic(self, n);
901     }
902 
903     LEAVE_BUFFERED(self)
904     return res;
905 }
906 
907 /*[clinic input]
908 _io._Buffered.read1
909     size as n: Py_ssize_t = -1
910     /
911 [clinic start generated code]*/
912 
913 static PyObject *
_io__Buffered_read1_impl(buffered * self,Py_ssize_t n)914 _io__Buffered_read1_impl(buffered *self, Py_ssize_t n)
915 /*[clinic end generated code: output=bcc4fb4e54d103a3 input=7d22de9630b61774]*/
916 {
917     Py_ssize_t have, r;
918     PyObject *res = NULL;
919 
920     CHECK_INITIALIZED(self)
921     if (n < 0) {
922         n = self->buffer_size;
923     }
924 
925     CHECK_CLOSED(self, "read of closed file")
926 
927     if (n == 0)
928         return PyBytes_FromStringAndSize(NULL, 0);
929 
930     /* Return up to n bytes.  If at least one byte is buffered, we
931        only return buffered bytes.  Otherwise, we do one raw read. */
932 
933     have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
934     if (have > 0) {
935         n = Py_MIN(have, n);
936         res = _bufferedreader_read_fast(self, n);
937         assert(res != Py_None);
938         return res;
939     }
940     res = PyBytes_FromStringAndSize(NULL, n);
941     if (res == NULL)
942         return NULL;
943     if (!ENTER_BUFFERED(self)) {
944         Py_DECREF(res);
945         return NULL;
946     }
947     _bufferedreader_reset_buf(self);
948     r = _bufferedreader_raw_read(self, PyBytes_AS_STRING(res), n);
949     LEAVE_BUFFERED(self)
950     if (r == -1) {
951         Py_DECREF(res);
952         return NULL;
953     }
954     if (r == -2)
955         r = 0;
956     if (n > r)
957         _PyBytes_Resize(&res, r);
958     return res;
959 }
960 
961 static PyObject *
_buffered_readinto_generic(buffered * self,Py_buffer * buffer,char readinto1)962 _buffered_readinto_generic(buffered *self, Py_buffer *buffer, char readinto1)
963 {
964     Py_ssize_t n, written = 0, remaining;
965     PyObject *res = NULL;
966 
967     CHECK_INITIALIZED(self)
968     CHECK_CLOSED(self, "readinto of closed file")
969 
970     n = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
971     if (n > 0) {
972         if (n >= buffer->len) {
973             memcpy(buffer->buf, self->buffer + self->pos, buffer->len);
974             self->pos += buffer->len;
975             return PyLong_FromSsize_t(buffer->len);
976         }
977         memcpy(buffer->buf, self->buffer + self->pos, n);
978         self->pos += n;
979         written = n;
980     }
981 
982     if (!ENTER_BUFFERED(self))
983         return NULL;
984 
985     if (self->writable) {
986         res = buffered_flush_and_rewind_unlocked(self);
987         if (res == NULL)
988             goto end;
989         Py_CLEAR(res);
990     }
991 
992     _bufferedreader_reset_buf(self);
993     self->pos = 0;
994 
995     for (remaining = buffer->len - written;
996          remaining > 0;
997          written += n, remaining -= n) {
998         /* If remaining bytes is larger than internal buffer size, copy
999          * directly into caller's buffer. */
1000         if (remaining > self->buffer_size) {
1001             n = _bufferedreader_raw_read(self, (char *) buffer->buf + written,
1002                                          remaining);
1003         }
1004 
1005         /* In readinto1 mode, we do not want to fill the internal
1006            buffer if we already have some data to return */
1007         else if (!(readinto1 && written)) {
1008             n = _bufferedreader_fill_buffer(self);
1009             if (n > 0) {
1010                 if (n > remaining)
1011                     n = remaining;
1012                 memcpy((char *) buffer->buf + written,
1013                        self->buffer + self->pos, n);
1014                 self->pos += n;
1015                 continue; /* short circuit */
1016             }
1017         }
1018         else
1019             n = 0;
1020 
1021         if (n == 0 || (n == -2 && written > 0))
1022             break;
1023         if (n < 0) {
1024             if (n == -2) {
1025                 Py_INCREF(Py_None);
1026                 res = Py_None;
1027             }
1028             goto end;
1029         }
1030 
1031         /* At most one read in readinto1 mode */
1032         if (readinto1) {
1033             written += n;
1034             break;
1035         }
1036     }
1037     res = PyLong_FromSsize_t(written);
1038 
1039 end:
1040     LEAVE_BUFFERED(self);
1041     return res;
1042 }
1043 
1044 /*[clinic input]
1045 _io._Buffered.readinto
1046     buffer: Py_buffer(accept={rwbuffer})
1047     /
1048 [clinic start generated code]*/
1049 
1050 static PyObject *
_io__Buffered_readinto_impl(buffered * self,Py_buffer * buffer)1051 _io__Buffered_readinto_impl(buffered *self, Py_buffer *buffer)
1052 /*[clinic end generated code: output=bcb376580b1d8170 input=ed6b98b7a20a3008]*/
1053 {
1054     return _buffered_readinto_generic(self, buffer, 0);
1055 }
1056 
1057 /*[clinic input]
1058 _io._Buffered.readinto1
1059     buffer: Py_buffer(accept={rwbuffer})
1060     /
1061 [clinic start generated code]*/
1062 
1063 static PyObject *
_io__Buffered_readinto1_impl(buffered * self,Py_buffer * buffer)1064 _io__Buffered_readinto1_impl(buffered *self, Py_buffer *buffer)
1065 /*[clinic end generated code: output=6e5c6ac5868205d6 input=4455c5d55fdf1687]*/
1066 {
1067     return _buffered_readinto_generic(self, buffer, 1);
1068 }
1069 
1070 
1071 static PyObject *
_buffered_readline(buffered * self,Py_ssize_t limit)1072 _buffered_readline(buffered *self, Py_ssize_t limit)
1073 {
1074     PyObject *res = NULL;
1075     PyObject *chunks = NULL;
1076     Py_ssize_t n;
1077     const char *start, *s, *end;
1078 
1079     CHECK_CLOSED(self, "readline of closed file")
1080 
1081     /* First, try to find a line in the buffer. This can run unlocked because
1082        the calls to the C API are simple enough that they can't trigger
1083        any thread switch. */
1084     n = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1085     if (limit >= 0 && n > limit)
1086         n = limit;
1087     start = self->buffer + self->pos;
1088     s = memchr(start, '\n', n);
1089     if (s != NULL) {
1090         res = PyBytes_FromStringAndSize(start, s - start + 1);
1091         if (res != NULL)
1092             self->pos += s - start + 1;
1093         goto end_unlocked;
1094     }
1095     if (n == limit) {
1096         res = PyBytes_FromStringAndSize(start, n);
1097         if (res != NULL)
1098             self->pos += n;
1099         goto end_unlocked;
1100     }
1101 
1102     if (!ENTER_BUFFERED(self))
1103         goto end_unlocked;
1104 
1105     /* Now we try to get some more from the raw stream */
1106     chunks = PyList_New(0);
1107     if (chunks == NULL)
1108         goto end;
1109     if (n > 0) {
1110         res = PyBytes_FromStringAndSize(start, n);
1111         if (res == NULL)
1112             goto end;
1113         if (PyList_Append(chunks, res) < 0) {
1114             Py_CLEAR(res);
1115             goto end;
1116         }
1117         Py_CLEAR(res);
1118         self->pos += n;
1119         if (limit >= 0)
1120             limit -= n;
1121     }
1122     if (self->writable) {
1123         PyObject *r = buffered_flush_and_rewind_unlocked(self);
1124         if (r == NULL)
1125             goto end;
1126         Py_DECREF(r);
1127     }
1128 
1129     for (;;) {
1130         _bufferedreader_reset_buf(self);
1131         n = _bufferedreader_fill_buffer(self);
1132         if (n == -1)
1133             goto end;
1134         if (n <= 0)
1135             break;
1136         if (limit >= 0 && n > limit)
1137             n = limit;
1138         start = self->buffer;
1139         end = start + n;
1140         s = start;
1141         while (s < end) {
1142             if (*s++ == '\n') {
1143                 res = PyBytes_FromStringAndSize(start, s - start);
1144                 if (res == NULL)
1145                     goto end;
1146                 self->pos = s - start;
1147                 goto found;
1148             }
1149         }
1150         res = PyBytes_FromStringAndSize(start, n);
1151         if (res == NULL)
1152             goto end;
1153         if (n == limit) {
1154             self->pos = n;
1155             break;
1156         }
1157         if (PyList_Append(chunks, res) < 0) {
1158             Py_CLEAR(res);
1159             goto end;
1160         }
1161         Py_CLEAR(res);
1162         if (limit >= 0)
1163             limit -= n;
1164     }
1165 found:
1166     if (res != NULL && PyList_Append(chunks, res) < 0) {
1167         Py_CLEAR(res);
1168         goto end;
1169     }
1170     Py_XSETREF(res, _PyBytes_Join(_PyIO_empty_bytes, chunks));
1171 
1172 end:
1173     LEAVE_BUFFERED(self)
1174 end_unlocked:
1175     Py_XDECREF(chunks);
1176     return res;
1177 }
1178 
1179 /*[clinic input]
1180 _io._Buffered.readline
1181     size: Py_ssize_t(accept={int, NoneType}) = -1
1182     /
1183 [clinic start generated code]*/
1184 
1185 static PyObject *
_io__Buffered_readline_impl(buffered * self,Py_ssize_t size)1186 _io__Buffered_readline_impl(buffered *self, Py_ssize_t size)
1187 /*[clinic end generated code: output=24dd2aa6e33be83c input=673b6240e315ef8a]*/
1188 {
1189     CHECK_INITIALIZED(self)
1190     return _buffered_readline(self, size);
1191 }
1192 
1193 
1194 static PyObject *
buffered_tell(buffered * self,PyObject * Py_UNUSED (ignored))1195 buffered_tell(buffered *self, PyObject *Py_UNUSED(ignored))
1196 {
1197     Py_off_t pos;
1198 
1199     CHECK_INITIALIZED(self)
1200     pos = _buffered_raw_tell(self);
1201     if (pos == -1)
1202         return NULL;
1203     pos -= RAW_OFFSET(self);
1204     /* TODO: sanity check (pos >= 0) */
1205     return PyLong_FromOff_t(pos);
1206 }
1207 
1208 /*[clinic input]
1209 _io._Buffered.seek
1210     target as targetobj: object
1211     whence: int = 0
1212     /
1213 [clinic start generated code]*/
1214 
1215 static PyObject *
_io__Buffered_seek_impl(buffered * self,PyObject * targetobj,int whence)1216 _io__Buffered_seek_impl(buffered *self, PyObject *targetobj, int whence)
1217 /*[clinic end generated code: output=7ae0e8dc46efdefb input=a9c4920bfcba6163]*/
1218 {
1219     Py_off_t target, n;
1220     PyObject *res = NULL;
1221 
1222     CHECK_INITIALIZED(self)
1223 
1224     /* Do some error checking instead of trusting OS 'seek()'
1225     ** error detection, just in case.
1226     */
1227     if ((whence < 0 || whence >2)
1228 #ifdef SEEK_HOLE
1229         && (whence != SEEK_HOLE)
1230 #endif
1231 #ifdef SEEK_DATA
1232         && (whence != SEEK_DATA)
1233 #endif
1234         ) {
1235         PyErr_Format(PyExc_ValueError,
1236                      "whence value %d unsupported", whence);
1237         return NULL;
1238     }
1239 
1240     CHECK_CLOSED(self, "seek of closed file")
1241 
1242     if (_PyIOBase_check_seekable(self->raw, Py_True) == NULL)
1243         return NULL;
1244 
1245     target = PyNumber_AsOff_t(targetobj, PyExc_ValueError);
1246     if (target == -1 && PyErr_Occurred())
1247         return NULL;
1248 
1249     /* SEEK_SET and SEEK_CUR are special because we could seek inside the
1250        buffer. Other whence values must be managed without this optimization.
1251        Some Operating Systems can provide additional values, like
1252        SEEK_HOLE/SEEK_DATA. */
1253     if (((whence == 0) || (whence == 1)) && self->readable) {
1254         Py_off_t current, avail;
1255         /* Check if seeking leaves us inside the current buffer,
1256            so as to return quickly if possible. Also, we needn't take the
1257            lock in this fast path.
1258            Don't know how to do that when whence == 2, though. */
1259         /* NOTE: RAW_TELL() can release the GIL but the object is in a stable
1260            state at this point. */
1261         current = RAW_TELL(self);
1262         avail = READAHEAD(self);
1263         if (avail > 0) {
1264             Py_off_t offset;
1265             if (whence == 0)
1266                 offset = target - (current - RAW_OFFSET(self));
1267             else
1268                 offset = target;
1269             if (offset >= -self->pos && offset <= avail) {
1270                 self->pos += offset;
1271                 return PyLong_FromOff_t(current - avail + offset);
1272             }
1273         }
1274     }
1275 
1276     if (!ENTER_BUFFERED(self))
1277         return NULL;
1278 
1279     /* Fallback: invoke raw seek() method and clear buffer */
1280     if (self->writable) {
1281         res = _bufferedwriter_flush_unlocked(self);
1282         if (res == NULL)
1283             goto end;
1284         Py_CLEAR(res);
1285     }
1286 
1287     /* TODO: align on block boundary and read buffer if needed? */
1288     if (whence == 1)
1289         target -= RAW_OFFSET(self);
1290     n = _buffered_raw_seek(self, target, whence);
1291     if (n == -1)
1292         goto end;
1293     self->raw_pos = -1;
1294     res = PyLong_FromOff_t(n);
1295     if (res != NULL && self->readable)
1296         _bufferedreader_reset_buf(self);
1297 
1298 end:
1299     LEAVE_BUFFERED(self)
1300     return res;
1301 }
1302 
1303 /*[clinic input]
1304 _io._Buffered.truncate
1305     pos: object = None
1306     /
1307 [clinic start generated code]*/
1308 
1309 static PyObject *
_io__Buffered_truncate_impl(buffered * self,PyObject * pos)1310 _io__Buffered_truncate_impl(buffered *self, PyObject *pos)
1311 /*[clinic end generated code: output=667ca03c60c270de input=8a1be34d57cca2d3]*/
1312 {
1313     PyObject *res = NULL;
1314 
1315     CHECK_INITIALIZED(self)
1316     CHECK_CLOSED(self, "truncate of closed file")
1317     if (!self->writable) {
1318         return bufferediobase_unsupported("truncate");
1319     }
1320     if (!ENTER_BUFFERED(self))
1321         return NULL;
1322 
1323     res = buffered_flush_and_rewind_unlocked(self);
1324     if (res == NULL) {
1325         goto end;
1326     }
1327     Py_CLEAR(res);
1328 
1329     res = PyObject_CallMethodOneArg(self->raw, _PyIO_str_truncate, pos);
1330     if (res == NULL)
1331         goto end;
1332     /* Reset cached position */
1333     if (_buffered_raw_tell(self) == -1)
1334         PyErr_Clear();
1335 
1336 end:
1337     LEAVE_BUFFERED(self)
1338     return res;
1339 }
1340 
1341 static PyObject *
buffered_iternext(buffered * self)1342 buffered_iternext(buffered *self)
1343 {
1344     PyObject *line;
1345     PyTypeObject *tp;
1346 
1347     CHECK_INITIALIZED(self);
1348 
1349     tp = Py_TYPE(self);
1350     if (tp == &PyBufferedReader_Type ||
1351         tp == &PyBufferedRandom_Type) {
1352         /* Skip method call overhead for speed */
1353         line = _buffered_readline(self, -1);
1354     }
1355     else {
1356         line = PyObject_CallMethodNoArgs((PyObject *)self,
1357                                              _PyIO_str_readline);
1358         if (line && !PyBytes_Check(line)) {
1359             PyErr_Format(PyExc_OSError,
1360                          "readline() should have returned a bytes object, "
1361                          "not '%.200s'", Py_TYPE(line)->tp_name);
1362             Py_DECREF(line);
1363             return NULL;
1364         }
1365     }
1366 
1367     if (line == NULL)
1368         return NULL;
1369 
1370     if (PyBytes_GET_SIZE(line) == 0) {
1371         /* Reached EOF or would have blocked */
1372         Py_DECREF(line);
1373         return NULL;
1374     }
1375 
1376     return line;
1377 }
1378 
1379 static PyObject *
buffered_repr(buffered * self)1380 buffered_repr(buffered *self)
1381 {
1382     PyObject *nameobj, *res;
1383 
1384     if (_PyObject_LookupAttrId((PyObject *) self, &PyId_name, &nameobj) < 0) {
1385         if (!PyErr_ExceptionMatches(PyExc_ValueError)) {
1386             return NULL;
1387         }
1388         /* Ignore ValueError raised if the underlying stream was detached */
1389         PyErr_Clear();
1390     }
1391     if (nameobj == NULL) {
1392         res = PyUnicode_FromFormat("<%s>", Py_TYPE(self)->tp_name);
1393     }
1394     else {
1395         int status = Py_ReprEnter((PyObject *)self);
1396         res = NULL;
1397         if (status == 0) {
1398             res = PyUnicode_FromFormat("<%s name=%R>",
1399                                        Py_TYPE(self)->tp_name, nameobj);
1400             Py_ReprLeave((PyObject *)self);
1401         }
1402         else if (status > 0) {
1403             PyErr_Format(PyExc_RuntimeError,
1404                          "reentrant call inside %s.__repr__",
1405                          Py_TYPE(self)->tp_name);
1406         }
1407         Py_DECREF(nameobj);
1408     }
1409     return res;
1410 }
1411 
1412 /*
1413  * class BufferedReader
1414  */
1415 
_bufferedreader_reset_buf(buffered * self)1416 static void _bufferedreader_reset_buf(buffered *self)
1417 {
1418     self->read_end = -1;
1419 }
1420 
1421 /*[clinic input]
1422 _io.BufferedReader.__init__
1423     raw: object
1424     buffer_size: Py_ssize_t(c_default="DEFAULT_BUFFER_SIZE") = DEFAULT_BUFFER_SIZE
1425 
1426 Create a new buffered reader using the given readable raw IO object.
1427 [clinic start generated code]*/
1428 
1429 static int
_io_BufferedReader___init___impl(buffered * self,PyObject * raw,Py_ssize_t buffer_size)1430 _io_BufferedReader___init___impl(buffered *self, PyObject *raw,
1431                                  Py_ssize_t buffer_size)
1432 /*[clinic end generated code: output=cddcfefa0ed294c4 input=fb887e06f11b4e48]*/
1433 {
1434     self->ok = 0;
1435     self->detached = 0;
1436 
1437     if (_PyIOBase_check_readable(raw, Py_True) == NULL)
1438         return -1;
1439 
1440     Py_INCREF(raw);
1441     Py_XSETREF(self->raw, raw);
1442     self->buffer_size = buffer_size;
1443     self->readable = 1;
1444     self->writable = 0;
1445 
1446     if (_buffered_init(self) < 0)
1447         return -1;
1448     _bufferedreader_reset_buf(self);
1449 
1450     self->fast_closed_checks = (Py_IS_TYPE(self, &PyBufferedReader_Type) &&
1451                                 Py_IS_TYPE(raw, &PyFileIO_Type));
1452 
1453     self->ok = 1;
1454     return 0;
1455 }
1456 
1457 static Py_ssize_t
_bufferedreader_raw_read(buffered * self,char * start,Py_ssize_t len)1458 _bufferedreader_raw_read(buffered *self, char *start, Py_ssize_t len)
1459 {
1460     Py_buffer buf;
1461     PyObject *memobj, *res;
1462     Py_ssize_t n;
1463     /* NOTE: the buffer needn't be released as its object is NULL. */
1464     if (PyBuffer_FillInfo(&buf, NULL, start, len, 0, PyBUF_CONTIG) == -1)
1465         return -1;
1466     memobj = PyMemoryView_FromBuffer(&buf);
1467     if (memobj == NULL)
1468         return -1;
1469     /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals() when EINTR
1470        occurs so we needn't do it ourselves.
1471        We then retry reading, ignoring the signal if no handler has
1472        raised (see issue #10956).
1473     */
1474     do {
1475         res = PyObject_CallMethodOneArg(self->raw, _PyIO_str_readinto, memobj);
1476     } while (res == NULL && _PyIO_trap_eintr());
1477     Py_DECREF(memobj);
1478     if (res == NULL)
1479         return -1;
1480     if (res == Py_None) {
1481         /* Non-blocking stream would have blocked. Special return code! */
1482         Py_DECREF(res);
1483         return -2;
1484     }
1485     n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1486     Py_DECREF(res);
1487 
1488     if (n == -1 && PyErr_Occurred()) {
1489         _PyErr_FormatFromCause(
1490             PyExc_OSError,
1491             "raw readinto() failed"
1492         );
1493         return -1;
1494     }
1495 
1496     if (n < 0 || n > len) {
1497         PyErr_Format(PyExc_OSError,
1498                      "raw readinto() returned invalid length %zd "
1499                      "(should have been between 0 and %zd)", n, len);
1500         return -1;
1501     }
1502     if (n > 0 && self->abs_pos != -1)
1503         self->abs_pos += n;
1504     return n;
1505 }
1506 
1507 static Py_ssize_t
_bufferedreader_fill_buffer(buffered * self)1508 _bufferedreader_fill_buffer(buffered *self)
1509 {
1510     Py_ssize_t start, len, n;
1511     if (VALID_READ_BUFFER(self))
1512         start = Py_SAFE_DOWNCAST(self->read_end, Py_off_t, Py_ssize_t);
1513     else
1514         start = 0;
1515     len = self->buffer_size - start;
1516     n = _bufferedreader_raw_read(self, self->buffer + start, len);
1517     if (n <= 0)
1518         return n;
1519     self->read_end = start + n;
1520     self->raw_pos = start + n;
1521     return n;
1522 }
1523 
1524 static PyObject *
_bufferedreader_read_all(buffered * self)1525 _bufferedreader_read_all(buffered *self)
1526 {
1527     Py_ssize_t current_size;
1528     PyObject *res = NULL, *data = NULL, *tmp = NULL, *chunks = NULL, *readall;
1529 
1530     /* First copy what we have in the current buffer. */
1531     current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1532     if (current_size) {
1533         data = PyBytes_FromStringAndSize(
1534             self->buffer + self->pos, current_size);
1535         if (data == NULL)
1536             return NULL;
1537         self->pos += current_size;
1538     }
1539     /* We're going past the buffer's bounds, flush it */
1540     if (self->writable) {
1541         tmp = buffered_flush_and_rewind_unlocked(self);
1542         if (tmp == NULL)
1543             goto cleanup;
1544         Py_CLEAR(tmp);
1545     }
1546     _bufferedreader_reset_buf(self);
1547 
1548     if (_PyObject_LookupAttr(self->raw, _PyIO_str_readall, &readall) < 0) {
1549         goto cleanup;
1550     }
1551     if (readall) {
1552         tmp = _PyObject_CallNoArgs(readall);
1553         Py_DECREF(readall);
1554         if (tmp == NULL)
1555             goto cleanup;
1556         if (tmp != Py_None && !PyBytes_Check(tmp)) {
1557             PyErr_SetString(PyExc_TypeError, "readall() should return bytes");
1558             goto cleanup;
1559         }
1560         if (current_size == 0) {
1561             res = tmp;
1562         } else {
1563             if (tmp != Py_None) {
1564                 PyBytes_Concat(&data, tmp);
1565             }
1566             res = data;
1567         }
1568         goto cleanup;
1569     }
1570 
1571     chunks = PyList_New(0);
1572     if (chunks == NULL)
1573         goto cleanup;
1574 
1575     while (1) {
1576         if (data) {
1577             if (PyList_Append(chunks, data) < 0)
1578                 goto cleanup;
1579             Py_CLEAR(data);
1580         }
1581 
1582         /* Read until EOF or until read() would block. */
1583         data = PyObject_CallMethodNoArgs(self->raw, _PyIO_str_read);
1584         if (data == NULL)
1585             goto cleanup;
1586         if (data != Py_None && !PyBytes_Check(data)) {
1587             PyErr_SetString(PyExc_TypeError, "read() should return bytes");
1588             goto cleanup;
1589         }
1590         if (data == Py_None || PyBytes_GET_SIZE(data) == 0) {
1591             if (current_size == 0) {
1592                 res = data;
1593                 goto cleanup;
1594             }
1595             else {
1596                 tmp = _PyBytes_Join(_PyIO_empty_bytes, chunks);
1597                 res = tmp;
1598                 goto cleanup;
1599             }
1600         }
1601         current_size += PyBytes_GET_SIZE(data);
1602         if (self->abs_pos != -1)
1603             self->abs_pos += PyBytes_GET_SIZE(data);
1604     }
1605 cleanup:
1606     /* res is either NULL or a borrowed ref */
1607     Py_XINCREF(res);
1608     Py_XDECREF(data);
1609     Py_XDECREF(tmp);
1610     Py_XDECREF(chunks);
1611     return res;
1612 }
1613 
1614 /* Read n bytes from the buffer if it can, otherwise return None.
1615    This function is simple enough that it can run unlocked. */
1616 static PyObject *
_bufferedreader_read_fast(buffered * self,Py_ssize_t n)1617 _bufferedreader_read_fast(buffered *self, Py_ssize_t n)
1618 {
1619     Py_ssize_t current_size;
1620 
1621     current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1622     if (n <= current_size) {
1623         /* Fast path: the data to read is fully buffered. */
1624         PyObject *res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
1625         if (res != NULL)
1626             self->pos += n;
1627         return res;
1628     }
1629     Py_RETURN_NONE;
1630 }
1631 
1632 /* Generic read function: read from the stream until enough bytes are read,
1633  * or until an EOF occurs or until read() would block.
1634  */
1635 static PyObject *
_bufferedreader_read_generic(buffered * self,Py_ssize_t n)1636 _bufferedreader_read_generic(buffered *self, Py_ssize_t n)
1637 {
1638     PyObject *res = NULL;
1639     Py_ssize_t current_size, remaining, written;
1640     char *out;
1641 
1642     current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1643     if (n <= current_size)
1644         return _bufferedreader_read_fast(self, n);
1645 
1646     res = PyBytes_FromStringAndSize(NULL, n);
1647     if (res == NULL)
1648         goto error;
1649     out = PyBytes_AS_STRING(res);
1650     remaining = n;
1651     written = 0;
1652     if (current_size > 0) {
1653         memcpy(out, self->buffer + self->pos, current_size);
1654         remaining -= current_size;
1655         written += current_size;
1656         self->pos += current_size;
1657     }
1658     /* Flush the write buffer if necessary */
1659     if (self->writable) {
1660         PyObject *r = buffered_flush_and_rewind_unlocked(self);
1661         if (r == NULL)
1662             goto error;
1663         Py_DECREF(r);
1664     }
1665     _bufferedreader_reset_buf(self);
1666     while (remaining > 0) {
1667         /* We want to read a whole block at the end into buffer.
1668            If we had readv() we could do this in one pass. */
1669         Py_ssize_t r = MINUS_LAST_BLOCK(self, remaining);
1670         if (r == 0)
1671             break;
1672         r = _bufferedreader_raw_read(self, out + written, r);
1673         if (r == -1)
1674             goto error;
1675         if (r == 0 || r == -2) {
1676             /* EOF occurred or read() would block. */
1677             if (r == 0 || written > 0) {
1678                 if (_PyBytes_Resize(&res, written))
1679                     goto error;
1680                 return res;
1681             }
1682             Py_DECREF(res);
1683             Py_RETURN_NONE;
1684         }
1685         remaining -= r;
1686         written += r;
1687     }
1688     assert(remaining <= self->buffer_size);
1689     self->pos = 0;
1690     self->raw_pos = 0;
1691     self->read_end = 0;
1692     /* NOTE: when the read is satisfied, we avoid issuing any additional
1693        reads, which could block indefinitely (e.g. on a socket).
1694        See issue #9550. */
1695     while (remaining > 0 && self->read_end < self->buffer_size) {
1696         Py_ssize_t r = _bufferedreader_fill_buffer(self);
1697         if (r == -1)
1698             goto error;
1699         if (r == 0 || r == -2) {
1700             /* EOF occurred or read() would block. */
1701             if (r == 0 || written > 0) {
1702                 if (_PyBytes_Resize(&res, written))
1703                     goto error;
1704                 return res;
1705             }
1706             Py_DECREF(res);
1707             Py_RETURN_NONE;
1708         }
1709         if (remaining > r) {
1710             memcpy(out + written, self->buffer + self->pos, r);
1711             written += r;
1712             self->pos += r;
1713             remaining -= r;
1714         }
1715         else if (remaining > 0) {
1716             memcpy(out + written, self->buffer + self->pos, remaining);
1717             written += remaining;
1718             self->pos += remaining;
1719             remaining = 0;
1720         }
1721         if (remaining == 0)
1722             break;
1723     }
1724 
1725     return res;
1726 
1727 error:
1728     Py_XDECREF(res);
1729     return NULL;
1730 }
1731 
1732 static PyObject *
_bufferedreader_peek_unlocked(buffered * self)1733 _bufferedreader_peek_unlocked(buffered *self)
1734 {
1735     Py_ssize_t have, r;
1736 
1737     have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1738     /* Constraints:
1739        1. we don't want to advance the file position.
1740        2. we don't want to lose block alignment, so we can't shift the buffer
1741           to make some place.
1742        Therefore, we either return `have` bytes (if > 0), or a full buffer.
1743     */
1744     if (have > 0) {
1745         return PyBytes_FromStringAndSize(self->buffer + self->pos, have);
1746     }
1747 
1748     /* Fill the buffer from the raw stream, and copy it to the result. */
1749     _bufferedreader_reset_buf(self);
1750     r = _bufferedreader_fill_buffer(self);
1751     if (r == -1)
1752         return NULL;
1753     if (r == -2)
1754         r = 0;
1755     self->pos = 0;
1756     return PyBytes_FromStringAndSize(self->buffer, r);
1757 }
1758 
1759 
1760 
1761 /*
1762  * class BufferedWriter
1763  */
1764 static void
_bufferedwriter_reset_buf(buffered * self)1765 _bufferedwriter_reset_buf(buffered *self)
1766 {
1767     self->write_pos = 0;
1768     self->write_end = -1;
1769 }
1770 
1771 /*[clinic input]
1772 _io.BufferedWriter.__init__
1773     raw: object
1774     buffer_size: Py_ssize_t(c_default="DEFAULT_BUFFER_SIZE") = DEFAULT_BUFFER_SIZE
1775 
1776 A buffer for a writeable sequential RawIO object.
1777 
1778 The constructor creates a BufferedWriter for the given writeable raw
1779 stream. If the buffer_size is not given, it defaults to
1780 DEFAULT_BUFFER_SIZE.
1781 [clinic start generated code]*/
1782 
1783 static int
_io_BufferedWriter___init___impl(buffered * self,PyObject * raw,Py_ssize_t buffer_size)1784 _io_BufferedWriter___init___impl(buffered *self, PyObject *raw,
1785                                  Py_ssize_t buffer_size)
1786 /*[clinic end generated code: output=c8942a020c0dee64 input=914be9b95e16007b]*/
1787 {
1788     self->ok = 0;
1789     self->detached = 0;
1790 
1791     if (_PyIOBase_check_writable(raw, Py_True) == NULL)
1792         return -1;
1793 
1794     Py_INCREF(raw);
1795     Py_XSETREF(self->raw, raw);
1796     self->readable = 0;
1797     self->writable = 1;
1798 
1799     self->buffer_size = buffer_size;
1800     if (_buffered_init(self) < 0)
1801         return -1;
1802     _bufferedwriter_reset_buf(self);
1803     self->pos = 0;
1804 
1805     self->fast_closed_checks = (Py_IS_TYPE(self, &PyBufferedWriter_Type) &&
1806                                 Py_IS_TYPE(raw, &PyFileIO_Type));
1807 
1808     self->ok = 1;
1809     return 0;
1810 }
1811 
1812 static Py_ssize_t
_bufferedwriter_raw_write(buffered * self,char * start,Py_ssize_t len)1813 _bufferedwriter_raw_write(buffered *self, char *start, Py_ssize_t len)
1814 {
1815     Py_buffer buf;
1816     PyObject *memobj, *res;
1817     Py_ssize_t n;
1818     int errnum;
1819     /* NOTE: the buffer needn't be released as its object is NULL. */
1820     if (PyBuffer_FillInfo(&buf, NULL, start, len, 1, PyBUF_CONTIG_RO) == -1)
1821         return -1;
1822     memobj = PyMemoryView_FromBuffer(&buf);
1823     if (memobj == NULL)
1824         return -1;
1825     /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals() when EINTR
1826        occurs so we needn't do it ourselves.
1827        We then retry writing, ignoring the signal if no handler has
1828        raised (see issue #10956).
1829     */
1830     do {
1831         errno = 0;
1832         res = PyObject_CallMethodOneArg(self->raw, _PyIO_str_write, memobj);
1833         errnum = errno;
1834     } while (res == NULL && _PyIO_trap_eintr());
1835     Py_DECREF(memobj);
1836     if (res == NULL)
1837         return -1;
1838     if (res == Py_None) {
1839         /* Non-blocking stream would have blocked. Special return code!
1840            Being paranoid we reset errno in case it is changed by code
1841            triggered by a decref.  errno is used by _set_BlockingIOError(). */
1842         Py_DECREF(res);
1843         errno = errnum;
1844         return -2;
1845     }
1846     n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1847     Py_DECREF(res);
1848     if (n < 0 || n > len) {
1849         PyErr_Format(PyExc_OSError,
1850                      "raw write() returned invalid length %zd "
1851                      "(should have been between 0 and %zd)", n, len);
1852         return -1;
1853     }
1854     if (n > 0 && self->abs_pos != -1)
1855         self->abs_pos += n;
1856     return n;
1857 }
1858 
1859 static PyObject *
_bufferedwriter_flush_unlocked(buffered * self)1860 _bufferedwriter_flush_unlocked(buffered *self)
1861 {
1862     Py_off_t n, rewind;
1863 
1864     if (!VALID_WRITE_BUFFER(self) || self->write_pos == self->write_end)
1865         goto end;
1866     /* First, rewind */
1867     rewind = RAW_OFFSET(self) + (self->pos - self->write_pos);
1868     if (rewind != 0) {
1869         n = _buffered_raw_seek(self, -rewind, 1);
1870         if (n < 0) {
1871             goto error;
1872         }
1873         self->raw_pos -= rewind;
1874     }
1875     while (self->write_pos < self->write_end) {
1876         n = _bufferedwriter_raw_write(self,
1877             self->buffer + self->write_pos,
1878             Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1879                              Py_off_t, Py_ssize_t));
1880         if (n == -1) {
1881             goto error;
1882         }
1883         else if (n == -2) {
1884             _set_BlockingIOError("write could not complete without blocking",
1885                                  0);
1886             goto error;
1887         }
1888         self->write_pos += n;
1889         self->raw_pos = self->write_pos;
1890         /* Partial writes can return successfully when interrupted by a
1891            signal (see write(2)).  We must run signal handlers before
1892            blocking another time, possibly indefinitely. */
1893         if (PyErr_CheckSignals() < 0)
1894             goto error;
1895     }
1896 
1897 
1898 end:
1899     /* This ensures that after return from this function,
1900        VALID_WRITE_BUFFER(self) returns false.
1901 
1902        This is a required condition because when a tell() is called
1903        after flushing and if VALID_READ_BUFFER(self) is false, we need
1904        VALID_WRITE_BUFFER(self) to be false to have
1905        RAW_OFFSET(self) == 0.
1906 
1907        Issue: https://bugs.python.org/issue32228 */
1908     _bufferedwriter_reset_buf(self);
1909     Py_RETURN_NONE;
1910 
1911 error:
1912     return NULL;
1913 }
1914 
1915 /*[clinic input]
1916 _io.BufferedWriter.write
1917     buffer: Py_buffer
1918     /
1919 [clinic start generated code]*/
1920 
1921 static PyObject *
_io_BufferedWriter_write_impl(buffered * self,Py_buffer * buffer)1922 _io_BufferedWriter_write_impl(buffered *self, Py_buffer *buffer)
1923 /*[clinic end generated code: output=7f8d1365759bfc6b input=dd87dd85fc7f8850]*/
1924 {
1925     PyObject *res = NULL;
1926     Py_ssize_t written, avail, remaining;
1927     Py_off_t offset;
1928 
1929     CHECK_INITIALIZED(self)
1930 
1931     if (!ENTER_BUFFERED(self))
1932         return NULL;
1933 
1934     /* Issue #31976: Check for closed file after acquiring the lock. Another
1935        thread could be holding the lock while closing the file. */
1936     if (IS_CLOSED(self)) {
1937         PyErr_SetString(PyExc_ValueError, "write to closed file");
1938         goto error;
1939     }
1940 
1941     /* Fast path: the data to write can be fully buffered. */
1942     if (!VALID_READ_BUFFER(self) && !VALID_WRITE_BUFFER(self)) {
1943         self->pos = 0;
1944         self->raw_pos = 0;
1945     }
1946     avail = Py_SAFE_DOWNCAST(self->buffer_size - self->pos, Py_off_t, Py_ssize_t);
1947     if (buffer->len <= avail) {
1948         memcpy(self->buffer + self->pos, buffer->buf, buffer->len);
1949         if (!VALID_WRITE_BUFFER(self) || self->write_pos > self->pos) {
1950             self->write_pos = self->pos;
1951         }
1952         ADJUST_POSITION(self, self->pos + buffer->len);
1953         if (self->pos > self->write_end)
1954             self->write_end = self->pos;
1955         written = buffer->len;
1956         goto end;
1957     }
1958 
1959     /* First write the current buffer */
1960     res = _bufferedwriter_flush_unlocked(self);
1961     if (res == NULL) {
1962         Py_ssize_t *w = _buffered_check_blocking_error();
1963         if (w == NULL)
1964             goto error;
1965         if (self->readable)
1966             _bufferedreader_reset_buf(self);
1967         /* Make some place by shifting the buffer. */
1968         assert(VALID_WRITE_BUFFER(self));
1969         memmove(self->buffer, self->buffer + self->write_pos,
1970                 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1971                                  Py_off_t, Py_ssize_t));
1972         self->write_end -= self->write_pos;
1973         self->raw_pos -= self->write_pos;
1974         self->pos -= self->write_pos;
1975         self->write_pos = 0;
1976         avail = Py_SAFE_DOWNCAST(self->buffer_size - self->write_end,
1977                                  Py_off_t, Py_ssize_t);
1978         if (buffer->len <= avail) {
1979             /* Everything can be buffered */
1980             PyErr_Clear();
1981             memcpy(self->buffer + self->write_end, buffer->buf, buffer->len);
1982             self->write_end += buffer->len;
1983             self->pos += buffer->len;
1984             written = buffer->len;
1985             goto end;
1986         }
1987         /* Buffer as much as possible. */
1988         memcpy(self->buffer + self->write_end, buffer->buf, avail);
1989         self->write_end += avail;
1990         self->pos += avail;
1991         /* XXX Modifying the existing exception e using the pointer w
1992            will change e.characters_written but not e.args[2].
1993            Therefore we just replace with a new error. */
1994         _set_BlockingIOError("write could not complete without blocking",
1995                              avail);
1996         goto error;
1997     }
1998     Py_CLEAR(res);
1999 
2000     /* Adjust the raw stream position if it is away from the logical stream
2001        position. This happens if the read buffer has been filled but not
2002        modified (and therefore _bufferedwriter_flush_unlocked() didn't rewind
2003        the raw stream by itself).
2004        Fixes issue #6629.
2005     */
2006     offset = RAW_OFFSET(self);
2007     if (offset != 0) {
2008         if (_buffered_raw_seek(self, -offset, 1) < 0)
2009             goto error;
2010         self->raw_pos -= offset;
2011     }
2012 
2013     /* Then write buf itself. At this point the buffer has been emptied. */
2014     remaining = buffer->len;
2015     written = 0;
2016     while (remaining > self->buffer_size) {
2017         Py_ssize_t n = _bufferedwriter_raw_write(
2018             self, (char *) buffer->buf + written, buffer->len - written);
2019         if (n == -1) {
2020             goto error;
2021         } else if (n == -2) {
2022             /* Write failed because raw file is non-blocking */
2023             if (remaining > self->buffer_size) {
2024                 /* Can't buffer everything, still buffer as much as possible */
2025                 memcpy(self->buffer,
2026                        (char *) buffer->buf + written, self->buffer_size);
2027                 self->raw_pos = 0;
2028                 ADJUST_POSITION(self, self->buffer_size);
2029                 self->write_end = self->buffer_size;
2030                 written += self->buffer_size;
2031                 _set_BlockingIOError("write could not complete without "
2032                                      "blocking", written);
2033                 goto error;
2034             }
2035             PyErr_Clear();
2036             break;
2037         }
2038         written += n;
2039         remaining -= n;
2040         /* Partial writes can return successfully when interrupted by a
2041            signal (see write(2)).  We must run signal handlers before
2042            blocking another time, possibly indefinitely. */
2043         if (PyErr_CheckSignals() < 0)
2044             goto error;
2045     }
2046     if (self->readable)
2047         _bufferedreader_reset_buf(self);
2048     if (remaining > 0) {
2049         memcpy(self->buffer, (char *) buffer->buf + written, remaining);
2050         written += remaining;
2051     }
2052     self->write_pos = 0;
2053     /* TODO: sanity check (remaining >= 0) */
2054     self->write_end = remaining;
2055     ADJUST_POSITION(self, remaining);
2056     self->raw_pos = 0;
2057 
2058 end:
2059     res = PyLong_FromSsize_t(written);
2060 
2061 error:
2062     LEAVE_BUFFERED(self)
2063     return res;
2064 }
2065 
2066 
2067 
2068 /*
2069  * BufferedRWPair
2070  */
2071 
2072 /* XXX The usefulness of this (compared to having two separate IO objects) is
2073  * questionable.
2074  */
2075 
2076 typedef struct {
2077     PyObject_HEAD
2078     buffered *reader;
2079     buffered *writer;
2080     PyObject *dict;
2081     PyObject *weakreflist;
2082 } rwpair;
2083 
2084 /*[clinic input]
2085 _io.BufferedRWPair.__init__
2086     reader: object
2087     writer: object
2088     buffer_size: Py_ssize_t(c_default="DEFAULT_BUFFER_SIZE") = DEFAULT_BUFFER_SIZE
2089     /
2090 
2091 A buffered reader and writer object together.
2092 
2093 A buffered reader object and buffered writer object put together to
2094 form a sequential IO object that can read and write. This is typically
2095 used with a socket or two-way pipe.
2096 
2097 reader and writer are RawIOBase objects that are readable and
2098 writeable respectively. If the buffer_size is omitted it defaults to
2099 DEFAULT_BUFFER_SIZE.
2100 [clinic start generated code]*/
2101 
2102 static int
_io_BufferedRWPair___init___impl(rwpair * self,PyObject * reader,PyObject * writer,Py_ssize_t buffer_size)2103 _io_BufferedRWPair___init___impl(rwpair *self, PyObject *reader,
2104                                  PyObject *writer, Py_ssize_t buffer_size)
2105 /*[clinic end generated code: output=327e73d1aee8f984 input=620d42d71f33a031]*/
2106 {
2107     if (_PyIOBase_check_readable(reader, Py_True) == NULL)
2108         return -1;
2109     if (_PyIOBase_check_writable(writer, Py_True) == NULL)
2110         return -1;
2111 
2112     self->reader = (buffered *) PyObject_CallFunction(
2113             (PyObject *) &PyBufferedReader_Type, "On", reader, buffer_size);
2114     if (self->reader == NULL)
2115         return -1;
2116 
2117     self->writer = (buffered *) PyObject_CallFunction(
2118             (PyObject *) &PyBufferedWriter_Type, "On", writer, buffer_size);
2119     if (self->writer == NULL) {
2120         Py_CLEAR(self->reader);
2121         return -1;
2122     }
2123 
2124     return 0;
2125 }
2126 
2127 static int
bufferedrwpair_traverse(rwpair * self,visitproc visit,void * arg)2128 bufferedrwpair_traverse(rwpair *self, visitproc visit, void *arg)
2129 {
2130     Py_VISIT(self->dict);
2131     return 0;
2132 }
2133 
2134 static int
bufferedrwpair_clear(rwpair * self)2135 bufferedrwpair_clear(rwpair *self)
2136 {
2137     Py_CLEAR(self->reader);
2138     Py_CLEAR(self->writer);
2139     Py_CLEAR(self->dict);
2140     return 0;
2141 }
2142 
2143 static void
bufferedrwpair_dealloc(rwpair * self)2144 bufferedrwpair_dealloc(rwpair *self)
2145 {
2146     _PyObject_GC_UNTRACK(self);
2147     if (self->weakreflist != NULL)
2148         PyObject_ClearWeakRefs((PyObject *)self);
2149     Py_CLEAR(self->reader);
2150     Py_CLEAR(self->writer);
2151     Py_CLEAR(self->dict);
2152     Py_TYPE(self)->tp_free((PyObject *) self);
2153 }
2154 
2155 static PyObject *
_forward_call(buffered * self,_Py_Identifier * name,PyObject * args)2156 _forward_call(buffered *self, _Py_Identifier *name, PyObject *args)
2157 {
2158     PyObject *func, *ret;
2159     if (self == NULL) {
2160         PyErr_SetString(PyExc_ValueError,
2161                         "I/O operation on uninitialized object");
2162         return NULL;
2163     }
2164 
2165     func = _PyObject_GetAttrId((PyObject *)self, name);
2166     if (func == NULL) {
2167         PyErr_SetString(PyExc_AttributeError, name->string);
2168         return NULL;
2169     }
2170 
2171     ret = PyObject_CallObject(func, args);
2172     Py_DECREF(func);
2173     return ret;
2174 }
2175 
2176 static PyObject *
bufferedrwpair_read(rwpair * self,PyObject * args)2177 bufferedrwpair_read(rwpair *self, PyObject *args)
2178 {
2179     return _forward_call(self->reader, &PyId_read, args);
2180 }
2181 
2182 static PyObject *
bufferedrwpair_peek(rwpair * self,PyObject * args)2183 bufferedrwpair_peek(rwpair *self, PyObject *args)
2184 {
2185     return _forward_call(self->reader, &PyId_peek, args);
2186 }
2187 
2188 static PyObject *
bufferedrwpair_read1(rwpair * self,PyObject * args)2189 bufferedrwpair_read1(rwpair *self, PyObject *args)
2190 {
2191     return _forward_call(self->reader, &PyId_read1, args);
2192 }
2193 
2194 static PyObject *
bufferedrwpair_readinto(rwpair * self,PyObject * args)2195 bufferedrwpair_readinto(rwpair *self, PyObject *args)
2196 {
2197     return _forward_call(self->reader, &PyId_readinto, args);
2198 }
2199 
2200 static PyObject *
bufferedrwpair_readinto1(rwpair * self,PyObject * args)2201 bufferedrwpair_readinto1(rwpair *self, PyObject *args)
2202 {
2203     return _forward_call(self->reader, &PyId_readinto1, args);
2204 }
2205 
2206 static PyObject *
bufferedrwpair_write(rwpair * self,PyObject * args)2207 bufferedrwpair_write(rwpair *self, PyObject *args)
2208 {
2209     return _forward_call(self->writer, &PyId_write, args);
2210 }
2211 
2212 static PyObject *
bufferedrwpair_flush(rwpair * self,PyObject * Py_UNUSED (ignored))2213 bufferedrwpair_flush(rwpair *self, PyObject *Py_UNUSED(ignored))
2214 {
2215     return _forward_call(self->writer, &PyId_flush, NULL);
2216 }
2217 
2218 static PyObject *
bufferedrwpair_readable(rwpair * self,PyObject * Py_UNUSED (ignored))2219 bufferedrwpair_readable(rwpair *self, PyObject *Py_UNUSED(ignored))
2220 {
2221     return _forward_call(self->reader, &PyId_readable, NULL);
2222 }
2223 
2224 static PyObject *
bufferedrwpair_writable(rwpair * self,PyObject * Py_UNUSED (ignored))2225 bufferedrwpair_writable(rwpair *self, PyObject *Py_UNUSED(ignored))
2226 {
2227     return _forward_call(self->writer, &PyId_writable, NULL);
2228 }
2229 
2230 static PyObject *
bufferedrwpair_close(rwpair * self,PyObject * Py_UNUSED (ignored))2231 bufferedrwpair_close(rwpair *self, PyObject *Py_UNUSED(ignored))
2232 {
2233     PyObject *exc = NULL, *val, *tb;
2234     PyObject *ret = _forward_call(self->writer, &PyId_close, NULL);
2235     if (ret == NULL)
2236         PyErr_Fetch(&exc, &val, &tb);
2237     else
2238         Py_DECREF(ret);
2239     ret = _forward_call(self->reader, &PyId_close, NULL);
2240     if (exc != NULL) {
2241         _PyErr_ChainExceptions(exc, val, tb);
2242         Py_CLEAR(ret);
2243     }
2244     return ret;
2245 }
2246 
2247 static PyObject *
bufferedrwpair_isatty(rwpair * self,PyObject * Py_UNUSED (ignored))2248 bufferedrwpair_isatty(rwpair *self, PyObject *Py_UNUSED(ignored))
2249 {
2250     PyObject *ret = _forward_call(self->writer, &PyId_isatty, NULL);
2251 
2252     if (ret != Py_False) {
2253         /* either True or exception */
2254         return ret;
2255     }
2256     Py_DECREF(ret);
2257 
2258     return _forward_call(self->reader, &PyId_isatty, NULL);
2259 }
2260 
2261 static PyObject *
bufferedrwpair_closed_get(rwpair * self,void * context)2262 bufferedrwpair_closed_get(rwpair *self, void *context)
2263 {
2264     if (self->writer == NULL) {
2265         PyErr_SetString(PyExc_RuntimeError,
2266                 "the BufferedRWPair object is being garbage-collected");
2267         return NULL;
2268     }
2269     return PyObject_GetAttr((PyObject *) self->writer, _PyIO_str_closed);
2270 }
2271 
2272 
2273 
2274 /*
2275  * BufferedRandom
2276  */
2277 
2278 /*[clinic input]
2279 _io.BufferedRandom.__init__
2280     raw: object
2281     buffer_size: Py_ssize_t(c_default="DEFAULT_BUFFER_SIZE") = DEFAULT_BUFFER_SIZE
2282 
2283 A buffered interface to random access streams.
2284 
2285 The constructor creates a reader and writer for a seekable stream,
2286 raw, given in the first argument. If the buffer_size is omitted it
2287 defaults to DEFAULT_BUFFER_SIZE.
2288 [clinic start generated code]*/
2289 
2290 static int
_io_BufferedRandom___init___impl(buffered * self,PyObject * raw,Py_ssize_t buffer_size)2291 _io_BufferedRandom___init___impl(buffered *self, PyObject *raw,
2292                                  Py_ssize_t buffer_size)
2293 /*[clinic end generated code: output=d3d64eb0f64e64a3 input=a4e818fb86d0e50c]*/
2294 {
2295     self->ok = 0;
2296     self->detached = 0;
2297 
2298     if (_PyIOBase_check_seekable(raw, Py_True) == NULL)
2299         return -1;
2300     if (_PyIOBase_check_readable(raw, Py_True) == NULL)
2301         return -1;
2302     if (_PyIOBase_check_writable(raw, Py_True) == NULL)
2303         return -1;
2304 
2305     Py_INCREF(raw);
2306     Py_XSETREF(self->raw, raw);
2307     self->buffer_size = buffer_size;
2308     self->readable = 1;
2309     self->writable = 1;
2310 
2311     if (_buffered_init(self) < 0)
2312         return -1;
2313     _bufferedreader_reset_buf(self);
2314     _bufferedwriter_reset_buf(self);
2315     self->pos = 0;
2316 
2317     self->fast_closed_checks = (Py_IS_TYPE(self, &PyBufferedRandom_Type) &&
2318                                 Py_IS_TYPE(raw, &PyFileIO_Type));
2319 
2320     self->ok = 1;
2321     return 0;
2322 }
2323 
2324 #include "clinic/bufferedio.c.h"
2325 
2326 
2327 static PyMethodDef bufferediobase_methods[] = {
2328     _IO__BUFFEREDIOBASE_DETACH_METHODDEF
2329     {"read", bufferediobase_read, METH_VARARGS, bufferediobase_read_doc},
2330     {"read1", bufferediobase_read1, METH_VARARGS, bufferediobase_read1_doc},
2331     _IO__BUFFEREDIOBASE_READINTO_METHODDEF
2332     _IO__BUFFEREDIOBASE_READINTO1_METHODDEF
2333     {"write", bufferediobase_write, METH_VARARGS, bufferediobase_write_doc},
2334     {NULL, NULL}
2335 };
2336 
2337 PyTypeObject PyBufferedIOBase_Type = {
2338     PyVarObject_HEAD_INIT(NULL, 0)
2339     "_io._BufferedIOBase",      /*tp_name*/
2340     0,                          /*tp_basicsize*/
2341     0,                          /*tp_itemsize*/
2342     0,                          /*tp_dealloc*/
2343     0,                          /*tp_vectorcall_offset*/
2344     0,                          /*tp_getattr*/
2345     0,                          /*tp_setattr*/
2346     0,                          /*tp_as_async*/
2347     0,                          /*tp_repr*/
2348     0,                          /*tp_as_number*/
2349     0,                          /*tp_as_sequence*/
2350     0,                          /*tp_as_mapping*/
2351     0,                          /*tp_hash */
2352     0,                          /*tp_call*/
2353     0,                          /*tp_str*/
2354     0,                          /*tp_getattro*/
2355     0,                          /*tp_setattro*/
2356     0,                          /*tp_as_buffer*/
2357     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,  /*tp_flags*/
2358     bufferediobase_doc,         /* tp_doc */
2359     0,                          /* tp_traverse */
2360     0,                          /* tp_clear */
2361     0,                          /* tp_richcompare */
2362     0,                          /* tp_weaklistoffset */
2363     0,                          /* tp_iter */
2364     0,                          /* tp_iternext */
2365     bufferediobase_methods,     /* tp_methods */
2366     0,                          /* tp_members */
2367     0,                          /* tp_getset */
2368     &PyIOBase_Type,             /* tp_base */
2369     0,                          /* tp_dict */
2370     0,                          /* tp_descr_get */
2371     0,                          /* tp_descr_set */
2372     0,                          /* tp_dictoffset */
2373     0,                          /* tp_init */
2374     0,                          /* tp_alloc */
2375     0,                          /* tp_new */
2376     0,                          /* tp_free */
2377     0,                          /* tp_is_gc */
2378     0,                          /* tp_bases */
2379     0,                          /* tp_mro */
2380     0,                          /* tp_cache */
2381     0,                          /* tp_subclasses */
2382     0,                          /* tp_weaklist */
2383     0,                          /* tp_del */
2384     0,                          /* tp_version_tag */
2385     0,                          /* tp_finalize */
2386 };
2387 
2388 
2389 static PyMethodDef bufferedreader_methods[] = {
2390     /* BufferedIOMixin methods */
2391     {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
2392     {"flush", (PyCFunction)buffered_simple_flush, METH_NOARGS},
2393     {"close", (PyCFunction)buffered_close, METH_NOARGS},
2394     {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
2395     {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
2396     {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
2397     {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
2398     {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O},
2399 
2400     _IO__BUFFERED_READ_METHODDEF
2401     _IO__BUFFERED_PEEK_METHODDEF
2402     _IO__BUFFERED_READ1_METHODDEF
2403     _IO__BUFFERED_READINTO_METHODDEF
2404     _IO__BUFFERED_READINTO1_METHODDEF
2405     _IO__BUFFERED_READLINE_METHODDEF
2406     _IO__BUFFERED_SEEK_METHODDEF
2407     {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
2408     _IO__BUFFERED_TRUNCATE_METHODDEF
2409     {"__sizeof__", (PyCFunction)buffered_sizeof, METH_NOARGS},
2410     {NULL, NULL}
2411 };
2412 
2413 static PyMemberDef bufferedreader_members[] = {
2414     {"raw", T_OBJECT, offsetof(buffered, raw), READONLY},
2415     {"_finalizing", T_BOOL, offsetof(buffered, finalizing), 0},
2416     {NULL}
2417 };
2418 
2419 static PyGetSetDef bufferedreader_getset[] = {
2420     {"closed", (getter)buffered_closed_get, NULL, NULL},
2421     {"name", (getter)buffered_name_get, NULL, NULL},
2422     {"mode", (getter)buffered_mode_get, NULL, NULL},
2423     {NULL}
2424 };
2425 
2426 
2427 PyTypeObject PyBufferedReader_Type = {
2428     PyVarObject_HEAD_INIT(NULL, 0)
2429     "_io.BufferedReader",       /*tp_name*/
2430     sizeof(buffered),           /*tp_basicsize*/
2431     0,                          /*tp_itemsize*/
2432     (destructor)buffered_dealloc,     /*tp_dealloc*/
2433     0,                          /*tp_vectorcall_offset*/
2434     0,                          /*tp_getattr*/
2435     0,                          /*tp_setattr*/
2436     0,                          /*tp_as_async*/
2437     (reprfunc)buffered_repr,    /*tp_repr*/
2438     0,                          /*tp_as_number*/
2439     0,                          /*tp_as_sequence*/
2440     0,                          /*tp_as_mapping*/
2441     0,                          /*tp_hash */
2442     0,                          /*tp_call*/
2443     0,                          /*tp_str*/
2444     0,                          /*tp_getattro*/
2445     0,                          /*tp_setattro*/
2446     0,                          /*tp_as_buffer*/
2447     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2448         | Py_TPFLAGS_HAVE_GC,   /*tp_flags*/
2449     _io_BufferedReader___init____doc__, /* tp_doc */
2450     (traverseproc)buffered_traverse, /* tp_traverse */
2451     (inquiry)buffered_clear,    /* tp_clear */
2452     0,                          /* tp_richcompare */
2453     offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
2454     0,                          /* tp_iter */
2455     (iternextfunc)buffered_iternext, /* tp_iternext */
2456     bufferedreader_methods,     /* tp_methods */
2457     bufferedreader_members,     /* tp_members */
2458     bufferedreader_getset,      /* tp_getset */
2459     0,                          /* tp_base */
2460     0,                          /* tp_dict */
2461     0,                          /* tp_descr_get */
2462     0,                          /* tp_descr_set */
2463     offsetof(buffered, dict), /* tp_dictoffset */
2464     _io_BufferedReader___init__, /* tp_init */
2465     0,                          /* tp_alloc */
2466     PyType_GenericNew,          /* tp_new */
2467     0,                          /* tp_free */
2468     0,                          /* tp_is_gc */
2469     0,                          /* tp_bases */
2470     0,                          /* tp_mro */
2471     0,                          /* tp_cache */
2472     0,                          /* tp_subclasses */
2473     0,                          /* tp_weaklist */
2474     0,                          /* tp_del */
2475     0,                          /* tp_version_tag */
2476     0,                          /* tp_finalize */
2477 };
2478 
2479 
2480 static PyMethodDef bufferedwriter_methods[] = {
2481     /* BufferedIOMixin methods */
2482     {"close", (PyCFunction)buffered_close, METH_NOARGS},
2483     {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
2484     {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
2485     {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
2486     {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
2487     {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
2488     {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O},
2489 
2490     _IO_BUFFEREDWRITER_WRITE_METHODDEF
2491     _IO__BUFFERED_TRUNCATE_METHODDEF
2492     {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
2493     _IO__BUFFERED_SEEK_METHODDEF
2494     {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
2495     {"__sizeof__", (PyCFunction)buffered_sizeof, METH_NOARGS},
2496     {NULL, NULL}
2497 };
2498 
2499 static PyMemberDef bufferedwriter_members[] = {
2500     {"raw", T_OBJECT, offsetof(buffered, raw), READONLY},
2501     {"_finalizing", T_BOOL, offsetof(buffered, finalizing), 0},
2502     {NULL}
2503 };
2504 
2505 static PyGetSetDef bufferedwriter_getset[] = {
2506     {"closed", (getter)buffered_closed_get, NULL, NULL},
2507     {"name", (getter)buffered_name_get, NULL, NULL},
2508     {"mode", (getter)buffered_mode_get, NULL, NULL},
2509     {NULL}
2510 };
2511 
2512 
2513 PyTypeObject PyBufferedWriter_Type = {
2514     PyVarObject_HEAD_INIT(NULL, 0)
2515     "_io.BufferedWriter",       /*tp_name*/
2516     sizeof(buffered),           /*tp_basicsize*/
2517     0,                          /*tp_itemsize*/
2518     (destructor)buffered_dealloc,     /*tp_dealloc*/
2519     0,                          /*tp_vectorcall_offset*/
2520     0,                          /*tp_getattr*/
2521     0,                          /*tp_setattr*/
2522     0,                          /*tp_as_async*/
2523     (reprfunc)buffered_repr,    /*tp_repr*/
2524     0,                          /*tp_as_number*/
2525     0,                          /*tp_as_sequence*/
2526     0,                          /*tp_as_mapping*/
2527     0,                          /*tp_hash */
2528     0,                          /*tp_call*/
2529     0,                          /*tp_str*/
2530     0,                          /*tp_getattro*/
2531     0,                          /*tp_setattro*/
2532     0,                          /*tp_as_buffer*/
2533     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2534         | Py_TPFLAGS_HAVE_GC,   /*tp_flags*/
2535     _io_BufferedWriter___init____doc__, /* tp_doc */
2536     (traverseproc)buffered_traverse, /* tp_traverse */
2537     (inquiry)buffered_clear,    /* tp_clear */
2538     0,                          /* tp_richcompare */
2539     offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
2540     0,                          /* tp_iter */
2541     0,                          /* tp_iternext */
2542     bufferedwriter_methods,     /* tp_methods */
2543     bufferedwriter_members,     /* tp_members */
2544     bufferedwriter_getset,      /* tp_getset */
2545     0,                          /* tp_base */
2546     0,                          /* tp_dict */
2547     0,                          /* tp_descr_get */
2548     0,                          /* tp_descr_set */
2549     offsetof(buffered, dict),   /* tp_dictoffset */
2550     _io_BufferedWriter___init__, /* tp_init */
2551     0,                          /* tp_alloc */
2552     PyType_GenericNew,          /* tp_new */
2553     0,                          /* tp_free */
2554     0,                          /* tp_is_gc */
2555     0,                          /* tp_bases */
2556     0,                          /* tp_mro */
2557     0,                          /* tp_cache */
2558     0,                          /* tp_subclasses */
2559     0,                          /* tp_weaklist */
2560     0,                          /* tp_del */
2561     0,                          /* tp_version_tag */
2562     0,                          /* tp_finalize */
2563 };
2564 
2565 
2566 static PyMethodDef bufferedrwpair_methods[] = {
2567     {"read", (PyCFunction)bufferedrwpair_read, METH_VARARGS},
2568     {"peek", (PyCFunction)bufferedrwpair_peek, METH_VARARGS},
2569     {"read1", (PyCFunction)bufferedrwpair_read1, METH_VARARGS},
2570     {"readinto", (PyCFunction)bufferedrwpair_readinto, METH_VARARGS},
2571     {"readinto1", (PyCFunction)bufferedrwpair_readinto1, METH_VARARGS},
2572 
2573     {"write", (PyCFunction)bufferedrwpair_write, METH_VARARGS},
2574     {"flush", (PyCFunction)bufferedrwpair_flush, METH_NOARGS},
2575 
2576     {"readable", (PyCFunction)bufferedrwpair_readable, METH_NOARGS},
2577     {"writable", (PyCFunction)bufferedrwpair_writable, METH_NOARGS},
2578 
2579     {"close", (PyCFunction)bufferedrwpair_close, METH_NOARGS},
2580     {"isatty", (PyCFunction)bufferedrwpair_isatty, METH_NOARGS},
2581 
2582     {NULL, NULL}
2583 };
2584 
2585 static PyGetSetDef bufferedrwpair_getset[] = {
2586     {"closed", (getter)bufferedrwpair_closed_get, NULL, NULL},
2587     {NULL}
2588 };
2589 
2590 PyTypeObject PyBufferedRWPair_Type = {
2591     PyVarObject_HEAD_INIT(NULL, 0)
2592     "_io.BufferedRWPair",       /*tp_name*/
2593     sizeof(rwpair),            /*tp_basicsize*/
2594     0,                          /*tp_itemsize*/
2595     (destructor)bufferedrwpair_dealloc,     /*tp_dealloc*/
2596     0,                          /*tp_vectorcall_offset*/
2597     0,                          /*tp_getattr*/
2598     0,                          /*tp_setattr*/
2599     0,                          /*tp_as_async*/
2600     0,                          /*tp_repr*/
2601     0,                          /*tp_as_number*/
2602     0,                          /*tp_as_sequence*/
2603     0,                          /*tp_as_mapping*/
2604     0,                          /*tp_hash */
2605     0,                          /*tp_call*/
2606     0,                          /*tp_str*/
2607     0,                          /*tp_getattro*/
2608     0,                          /*tp_setattro*/
2609     0,                          /*tp_as_buffer*/
2610     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2611         | Py_TPFLAGS_HAVE_GC,   /* tp_flags */
2612     _io_BufferedRWPair___init____doc__, /* tp_doc */
2613     (traverseproc)bufferedrwpair_traverse, /* tp_traverse */
2614     (inquiry)bufferedrwpair_clear, /* tp_clear */
2615     0,                          /* tp_richcompare */
2616     offsetof(rwpair, weakreflist), /*tp_weaklistoffset*/
2617     0,                          /* tp_iter */
2618     0,                          /* tp_iternext */
2619     bufferedrwpair_methods,     /* tp_methods */
2620     0,                          /* tp_members */
2621     bufferedrwpair_getset,      /* tp_getset */
2622     0,                          /* tp_base */
2623     0,                          /* tp_dict */
2624     0,                          /* tp_descr_get */
2625     0,                          /* tp_descr_set */
2626     offsetof(rwpair, dict),     /* tp_dictoffset */
2627     _io_BufferedRWPair___init__, /* tp_init */
2628     0,                          /* tp_alloc */
2629     PyType_GenericNew,          /* tp_new */
2630     0,                          /* tp_free */
2631     0,                          /* tp_is_gc */
2632     0,                          /* tp_bases */
2633     0,                          /* tp_mro */
2634     0,                          /* tp_cache */
2635     0,                          /* tp_subclasses */
2636     0,                          /* tp_weaklist */
2637     0,                          /* tp_del */
2638     0,                          /* tp_version_tag */
2639     0,                          /* tp_finalize */
2640 };
2641 
2642 
2643 static PyMethodDef bufferedrandom_methods[] = {
2644     /* BufferedIOMixin methods */
2645     {"close", (PyCFunction)buffered_close, METH_NOARGS},
2646     {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
2647     {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
2648     {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
2649     {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
2650     {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
2651     {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
2652     {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O},
2653 
2654     {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
2655 
2656     _IO__BUFFERED_SEEK_METHODDEF
2657     {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
2658     _IO__BUFFERED_TRUNCATE_METHODDEF
2659     _IO__BUFFERED_READ_METHODDEF
2660     _IO__BUFFERED_READ1_METHODDEF
2661     _IO__BUFFERED_READINTO_METHODDEF
2662     _IO__BUFFERED_READINTO1_METHODDEF
2663     _IO__BUFFERED_READLINE_METHODDEF
2664     _IO__BUFFERED_PEEK_METHODDEF
2665     _IO_BUFFEREDWRITER_WRITE_METHODDEF
2666     {"__sizeof__", (PyCFunction)buffered_sizeof, METH_NOARGS},
2667     {NULL, NULL}
2668 };
2669 
2670 static PyMemberDef bufferedrandom_members[] = {
2671     {"raw", T_OBJECT, offsetof(buffered, raw), READONLY},
2672     {"_finalizing", T_BOOL, offsetof(buffered, finalizing), 0},
2673     {NULL}
2674 };
2675 
2676 static PyGetSetDef bufferedrandom_getset[] = {
2677     {"closed", (getter)buffered_closed_get, NULL, NULL},
2678     {"name", (getter)buffered_name_get, NULL, NULL},
2679     {"mode", (getter)buffered_mode_get, NULL, NULL},
2680     {NULL}
2681 };
2682 
2683 
2684 PyTypeObject PyBufferedRandom_Type = {
2685     PyVarObject_HEAD_INIT(NULL, 0)
2686     "_io.BufferedRandom",       /*tp_name*/
2687     sizeof(buffered),           /*tp_basicsize*/
2688     0,                          /*tp_itemsize*/
2689     (destructor)buffered_dealloc,     /*tp_dealloc*/
2690     0,                          /*tp_vectorcall_offset*/
2691     0,                          /*tp_getattr*/
2692     0,                          /*tp_setattr*/
2693     0,                          /*tp_as_async*/
2694     (reprfunc)buffered_repr,    /*tp_repr*/
2695     0,                          /*tp_as_number*/
2696     0,                          /*tp_as_sequence*/
2697     0,                          /*tp_as_mapping*/
2698     0,                          /*tp_hash */
2699     0,                          /*tp_call*/
2700     0,                          /*tp_str*/
2701     0,                          /*tp_getattro*/
2702     0,                          /*tp_setattro*/
2703     0,                          /*tp_as_buffer*/
2704     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2705         | Py_TPFLAGS_HAVE_GC,   /*tp_flags*/
2706     _io_BufferedRandom___init____doc__, /* tp_doc */
2707     (traverseproc)buffered_traverse, /* tp_traverse */
2708     (inquiry)buffered_clear,    /* tp_clear */
2709     0,                          /* tp_richcompare */
2710     offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
2711     0,                          /* tp_iter */
2712     (iternextfunc)buffered_iternext, /* tp_iternext */
2713     bufferedrandom_methods,     /* tp_methods */
2714     bufferedrandom_members,     /* tp_members */
2715     bufferedrandom_getset,      /* tp_getset */
2716     0,                          /* tp_base */
2717     0,                          /*tp_dict*/
2718     0,                          /* tp_descr_get */
2719     0,                          /* tp_descr_set */
2720     offsetof(buffered, dict), /*tp_dictoffset*/
2721     _io_BufferedRandom___init__, /* tp_init */
2722     0,                          /* tp_alloc */
2723     PyType_GenericNew,          /* tp_new */
2724     0,                          /* tp_free */
2725     0,                          /* tp_is_gc */
2726     0,                          /* tp_bases */
2727     0,                          /* tp_mro */
2728     0,                          /* tp_cache */
2729     0,                          /* tp_subclasses */
2730     0,                          /* tp_weaklist */
2731     0,                          /* tp_del */
2732     0,                          /* tp_version_tag */
2733     0,                          /* tp_finalize */
2734 };
2735