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