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