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