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