Branch data Line data Source code
1 : : /* Author: Daniel Stutzbach */
2 : :
3 : : #define PY_SSIZE_T_CLEAN
4 : : #include "Python.h"
5 : : #include "pycore_fileutils.h" // _Py_BEGIN_SUPPRESS_IPH
6 : : #include "pycore_object.h" // _PyObject_GC_UNTRACK()
7 : : #include "structmember.h" // PyMemberDef
8 : : #include <stdbool.h>
9 : : #ifdef HAVE_SYS_TYPES_H
10 : : #include <sys/types.h>
11 : : #endif
12 : : #ifdef HAVE_SYS_STAT_H
13 : : #include <sys/stat.h>
14 : : #endif
15 : : #ifdef HAVE_IO_H
16 : : #include <io.h>
17 : : #endif
18 : : #ifdef HAVE_FCNTL_H
19 : : #include <fcntl.h>
20 : : #endif
21 : : #include <stddef.h> /* For offsetof */
22 : : #include "_iomodule.h"
23 : :
24 : : /*
25 : : * Known likely problems:
26 : : *
27 : : * - Files larger then 2**32-1
28 : : * - Files with unicode filenames
29 : : * - Passing numbers greater than 2**32-1 when an integer is expected
30 : : * - Making it work on Windows and other oddball platforms
31 : : *
32 : : * To Do:
33 : : *
34 : : * - autoconfify header file inclusion
35 : : */
36 : :
37 : : #ifdef MS_WINDOWS
38 : : /* can simulate truncate with Win32 API functions; see file_truncate */
39 : : #define HAVE_FTRUNCATE
40 : : #define WIN32_LEAN_AND_MEAN
41 : : #include <windows.h>
42 : : #endif
43 : :
44 : : #if BUFSIZ < (8*1024)
45 : : #define SMALLCHUNK (8*1024)
46 : : #elif (BUFSIZ >= (2 << 25))
47 : : #error "unreasonable BUFSIZ > 64 MiB defined"
48 : : #else
49 : : #define SMALLCHUNK BUFSIZ
50 : : #endif
51 : :
52 : : /*[clinic input]
53 : : module _io
54 : : class _io.FileIO "fileio *" "&PyFileIO_Type"
55 : : [clinic start generated code]*/
56 : : /*[clinic end generated code: output=da39a3ee5e6b4b0d input=1c77708b41fda70c]*/
57 : :
58 : : typedef struct {
59 : : PyObject_HEAD
60 : : int fd;
61 : : unsigned int created : 1;
62 : : unsigned int readable : 1;
63 : : unsigned int writable : 1;
64 : : unsigned int appending : 1;
65 : : signed int seekable : 2; /* -1 means unknown */
66 : : unsigned int closefd : 1;
67 : : char finalizing;
68 : : unsigned int blksize;
69 : : PyObject *weakreflist;
70 : : PyObject *dict;
71 : : } fileio;
72 : :
73 : : PyTypeObject PyFileIO_Type;
74 : :
75 : : #define PyFileIO_Check(op) (PyObject_TypeCheck((op), &PyFileIO_Type))
76 : :
77 : : /* Forward declarations */
78 : : static PyObject* portable_lseek(fileio *self, PyObject *posobj, int whence, bool suppress_pipe_error);
79 : :
80 : : int
81 : 5041130 : _PyFileIO_closed(PyObject *self)
82 : : {
83 : 5041130 : return ((fileio *)self)->fd < 0;
84 : : }
85 : :
86 : : /* Because this can call arbitrary code, it shouldn't be called when
87 : : the refcount is 0 (that is, not directly from tp_dealloc unless
88 : : the refcount has been temporarily re-incremented). */
89 : : static PyObject *
90 : 9285 : fileio_dealloc_warn(fileio *self, PyObject *source)
91 : : {
92 [ + - + + ]: 9285 : if (self->fd >= 0 && self->closefd) {
93 : : PyObject *exc, *val, *tb;
94 : 32 : PyErr_Fetch(&exc, &val, &tb);
95 [ - + ]: 32 : if (PyErr_ResourceWarning(source, 1, "unclosed file %R", source)) {
96 : : /* Spurious errors can appear at shutdown */
97 [ # # ]: 0 : if (PyErr_ExceptionMatches(PyExc_Warning))
98 : 0 : PyErr_WriteUnraisable((PyObject *) self);
99 : : }
100 : 32 : PyErr_Restore(exc, val, tb);
101 : : }
102 : 9285 : Py_RETURN_NONE;
103 : : }
104 : :
105 : : /* Returns 0 on success, -1 with exception set on failure. */
106 : : static int
107 : 294942 : internal_close(fileio *self)
108 : : {
109 : 294942 : int err = 0;
110 : 294942 : int save_errno = 0;
111 [ + + ]: 294942 : if (self->fd >= 0) {
112 : 294860 : int fd = self->fd;
113 : 294860 : self->fd = -1;
114 : : /* fd is accessible and someone else may have closed it */
115 : 294860 : Py_BEGIN_ALLOW_THREADS
116 : : _Py_BEGIN_SUPPRESS_IPH
117 : 294860 : err = close(fd);
118 [ + + ]: 294860 : if (err < 0)
119 : 20 : save_errno = errno;
120 : : _Py_END_SUPPRESS_IPH
121 : 294860 : Py_END_ALLOW_THREADS
122 : : }
123 [ + + ]: 294935 : if (err < 0) {
124 : 20 : errno = save_errno;
125 : 20 : PyErr_SetFromErrno(PyExc_OSError);
126 : 20 : return -1;
127 : : }
128 : 294915 : return 0;
129 : : }
130 : :
131 : : /*[clinic input]
132 : : _io.FileIO.close
133 : :
134 : : Close the file.
135 : :
136 : : A closed file cannot be used for further I/O operations. close() may be
137 : : called more than once without error.
138 : : [clinic start generated code]*/
139 : :
140 : : static PyObject *
141 : 305855 : _io_FileIO_close_impl(fileio *self)
142 : : /*[clinic end generated code: output=7737a319ef3bad0b input=f35231760d54a522]*/
143 : : {
144 : : PyObject *res;
145 : : PyObject *exc, *val, *tb;
146 : : int rc;
147 : 305855 : res = PyObject_CallMethodOneArg((PyObject*)&PyRawIOBase_Type,
148 : : &_Py_ID(close), (PyObject *)self);
149 [ + + ]: 305855 : if (!self->closefd) {
150 : 10952 : self->fd = -1;
151 : 10952 : return res;
152 : : }
153 [ + + ]: 294903 : if (res == NULL)
154 : 4 : PyErr_Fetch(&exc, &val, &tb);
155 [ + + ]: 294903 : if (self->finalizing) {
156 : 7 : PyObject *r = fileio_dealloc_warn(self, (PyObject *) self);
157 [ + - ]: 7 : if (r)
158 : 7 : Py_DECREF(r);
159 : : else
160 : 0 : PyErr_Clear();
161 : : }
162 : 294903 : rc = internal_close(self);
163 [ + + ]: 294896 : if (res == NULL)
164 : 4 : _PyErr_ChainExceptions(exc, val, tb);
165 [ + + ]: 294896 : if (rc < 0)
166 [ + - ]: 20 : Py_CLEAR(res);
167 : 294896 : return res;
168 : : }
169 : :
170 : : static PyObject *
171 : 314650 : fileio_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
172 : : {
173 : : fileio *self;
174 : :
175 : : assert(type != NULL && type->tp_alloc != NULL);
176 : :
177 : 314650 : self = (fileio *) type->tp_alloc(type, 0);
178 [ + - ]: 314650 : if (self != NULL) {
179 : 314650 : self->fd = -1;
180 : 314650 : self->created = 0;
181 : 314650 : self->readable = 0;
182 : 314650 : self->writable = 0;
183 : 314650 : self->appending = 0;
184 : 314650 : self->seekable = -1;
185 : 314650 : self->blksize = 0;
186 : 314650 : self->closefd = 1;
187 : 314650 : self->weakreflist = NULL;
188 : : }
189 : :
190 : 314650 : return (PyObject *) self;
191 : : }
192 : :
193 : : #ifdef O_CLOEXEC
194 : : extern int _Py_open_cloexec_works;
195 : : #endif
196 : :
197 : : /*[clinic input]
198 : : _io.FileIO.__init__
199 : : file as nameobj: object
200 : : mode: str = "r"
201 : : closefd: bool(accept={int}) = True
202 : : opener: object = None
203 : :
204 : : Open a file.
205 : :
206 : : The mode can be 'r' (default), 'w', 'x' or 'a' for reading,
207 : : writing, exclusive creation or appending. The file will be created if it
208 : : doesn't exist when opened for writing or appending; it will be truncated
209 : : when opened for writing. A FileExistsError will be raised if it already
210 : : exists when opened for creating. Opening a file for creating implies
211 : : writing so this mode behaves in a similar way to 'w'.Add a '+' to the mode
212 : : to allow simultaneous reading and writing. A custom opener can be used by
213 : : passing a callable as *opener*. The underlying file descriptor for the file
214 : : object is then obtained by calling opener with (*name*, *flags*).
215 : : *opener* must return an open file descriptor (passing os.open as *opener*
216 : : results in functionality similar to passing None).
217 : : [clinic start generated code]*/
218 : :
219 : : static int
220 : 314650 : _io_FileIO___init___impl(fileio *self, PyObject *nameobj, const char *mode,
221 : : int closefd, PyObject *opener)
222 : : /*[clinic end generated code: output=23413f68e6484bbd input=1596c9157a042a39]*/
223 : : {
224 : : #ifdef MS_WINDOWS
225 : : Py_UNICODE *widename = NULL;
226 : : #else
227 : 314650 : const char *name = NULL;
228 : : #endif
229 : 314650 : PyObject *stringobj = NULL;
230 : : const char *s;
231 : 314650 : int ret = 0;
232 : 314650 : int rwa = 0, plus = 0;
233 : 314650 : int flags = 0;
234 : 314650 : int fd = -1;
235 : 314650 : int fd_is_own = 0;
236 : : #ifdef O_CLOEXEC
237 : 314650 : int *atomic_flag_works = &_Py_open_cloexec_works;
238 : : #elif !defined(MS_WINDOWS)
239 : : int *atomic_flag_works = NULL;
240 : : #endif
241 : : struct _Py_stat_struct fdfstat;
242 : : int fstat_result;
243 : 314650 : int async_err = 0;
244 : :
245 : : assert(PyFileIO_Check(self));
246 [ + + ]: 314650 : if (self->fd >= 0) {
247 [ - + ]: 1 : if (self->closefd) {
248 : : /* Have to close the existing file first. */
249 [ # # ]: 0 : if (internal_close(self) < 0)
250 : 0 : return -1;
251 : : }
252 : : else
253 : 1 : self->fd = -1;
254 : : }
255 : :
256 : 314650 : fd = _PyLong_AsInt(nameobj);
257 [ + + ]: 314650 : if (fd < 0) {
258 [ + + ]: 285700 : if (!PyErr_Occurred()) {
259 : 1 : PyErr_SetString(PyExc_ValueError,
260 : : "negative file descriptor");
261 : 1 : return -1;
262 : : }
263 : 285699 : PyErr_Clear();
264 : : }
265 : :
266 [ + + ]: 314649 : if (fd < 0) {
267 : : #ifdef MS_WINDOWS
268 : : if (!PyUnicode_FSDecoder(nameobj, &stringobj)) {
269 : : return -1;
270 : : }
271 : : widename = PyUnicode_AsWideCharString(stringobj, NULL);
272 : : if (widename == NULL)
273 : : return -1;
274 : : #else
275 [ + + ]: 285699 : if (!PyUnicode_FSConverter(nameobj, &stringobj)) {
276 : 9 : return -1;
277 : : }
278 : 285690 : name = PyBytes_AS_STRING(stringobj);
279 : : #endif
280 : : }
281 : :
282 : 314640 : s = mode;
283 [ + + ]: 640881 : while (*s) {
284 [ + + + + : 326247 : switch (*s++) {
+ + + ]
285 : 530 : case 'x':
286 [ - + ]: 530 : if (rwa) {
287 : 0 : bad_mode:
288 : 3 : PyErr_SetString(PyExc_ValueError,
289 : : "Must have exactly one of create/read/write/append "
290 : : "mode and at most one plus");
291 : 3 : goto error;
292 : : }
293 : 530 : rwa = 1;
294 : 530 : self->created = 1;
295 : 530 : self->writable = 1;
296 : 530 : flags |= O_EXCL | O_CREAT;
297 : 530 : break;
298 : 257256 : case 'r':
299 [ - + ]: 257256 : if (rwa)
300 : 0 : goto bad_mode;
301 : 257256 : rwa = 1;
302 : 257256 : self->readable = 1;
303 : 257256 : break;
304 : 55673 : case 'w':
305 [ + + ]: 55673 : if (rwa)
306 : 1 : goto bad_mode;
307 : 55672 : rwa = 1;
308 : 55672 : self->writable = 1;
309 : 55672 : flags |= O_CREAT | O_TRUNC;
310 : 55672 : break;
311 : 1179 : case 'a':
312 [ - + ]: 1179 : if (rwa)
313 : 0 : goto bad_mode;
314 : 1179 : rwa = 1;
315 : 1179 : self->writable = 1;
316 : 1179 : self->appending = 1;
317 : 1179 : flags |= O_APPEND | O_CREAT;
318 : 1179 : break;
319 : 7524 : case 'b':
320 : 7524 : break;
321 : 4080 : case '+':
322 [ - + ]: 4080 : if (plus)
323 : 0 : goto bad_mode;
324 : 4080 : self->readable = self->writable = 1;
325 : 4080 : plus = 1;
326 : 4080 : break;
327 : 5 : default:
328 : 5 : PyErr_Format(PyExc_ValueError,
329 : : "invalid mode: %.200s", mode);
330 : 5 : goto error;
331 : : }
332 : : }
333 : :
334 [ + + ]: 314634 : if (!rwa)
335 : 2 : goto bad_mode;
336 : :
337 [ + + + + ]: 314632 : if (self->readable && self->writable)
338 : 4080 : flags |= O_RDWR;
339 [ + + ]: 310552 : else if (self->readable)
340 : 255750 : flags |= O_RDONLY;
341 : : else
342 : 54802 : flags |= O_WRONLY;
343 : :
344 : : #ifdef O_BINARY
345 : : flags |= O_BINARY;
346 : : #endif
347 : :
348 : : #ifdef MS_WINDOWS
349 : : flags |= O_NOINHERIT;
350 : : #elif defined(O_CLOEXEC)
351 : 314632 : flags |= O_CLOEXEC;
352 : : #endif
353 : :
354 [ + + ]: 314632 : if (PySys_Audit("open", "Osi", nameobj, mode, flags) < 0) {
355 : 5 : goto error;
356 : : }
357 : :
358 [ + + ]: 314627 : if (fd >= 0) {
359 : 28949 : self->fd = fd;
360 : 28949 : self->closefd = closefd;
361 : : }
362 : : else {
363 : 285678 : self->closefd = 1;
364 [ + + ]: 285678 : if (!closefd) {
365 : 2 : PyErr_SetString(PyExc_ValueError,
366 : : "Cannot use closefd=False with file name");
367 : 2 : goto error;
368 : : }
369 : :
370 : 285676 : errno = 0;
371 [ + + ]: 285676 : if (opener == Py_None) {
372 : : do {
373 : 283618 : Py_BEGIN_ALLOW_THREADS
374 : : #ifdef MS_WINDOWS
375 : : self->fd = _wopen(widename, flags, 0666);
376 : : #else
377 : 283618 : self->fd = open(name, flags, 0666);
378 : : #endif
379 : 283618 : Py_END_ALLOW_THREADS
380 [ + + + + : 283620 : } while (self->fd < 0 && errno == EINTR &&
+ - ]
381 : 3 : !(async_err = PyErr_CheckSignals()));
382 : :
383 [ - + ]: 283614 : if (async_err)
384 : 0 : goto error;
385 : : }
386 : : else {
387 : : PyObject *fdobj;
388 : :
389 : : #ifndef MS_WINDOWS
390 : : /* the opener may clear the atomic flag */
391 : 2061 : atomic_flag_works = NULL;
392 : : #endif
393 : :
394 : 2061 : fdobj = PyObject_CallFunction(opener, "Oi", nameobj, flags);
395 [ + + ]: 2061 : if (fdobj == NULL)
396 : 1 : goto error;
397 [ - + ]: 2060 : if (!PyLong_Check(fdobj)) {
398 : 0 : Py_DECREF(fdobj);
399 : 0 : PyErr_SetString(PyExc_TypeError,
400 : : "expected integer from opener");
401 : 0 : goto error;
402 : : }
403 : :
404 : 2060 : self->fd = _PyLong_AsInt(fdobj);
405 : 2060 : Py_DECREF(fdobj);
406 [ + + ]: 2060 : if (self->fd < 0) {
407 [ + - ]: 4 : if (!PyErr_Occurred()) {
408 : : /* The opener returned a negative but didn't set an
409 : : exception. See issue #27066 */
410 : 4 : PyErr_Format(PyExc_ValueError,
411 : : "opener returned %d", self->fd);
412 : : }
413 : 4 : goto error;
414 : : }
415 : : }
416 : :
417 : 285670 : fd_is_own = 1;
418 [ + + ]: 285670 : if (self->fd < 0) {
419 : 8656 : PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, nameobj);
420 : 8656 : goto error;
421 : : }
422 : :
423 : : #ifndef MS_WINDOWS
424 [ - + ]: 277014 : if (_Py_set_inheritable(self->fd, 0, atomic_flag_works) < 0)
425 : 0 : goto error;
426 : : #endif
427 : : }
428 : :
429 : 305963 : self->blksize = DEFAULT_BUFFER_SIZE;
430 : 305963 : Py_BEGIN_ALLOW_THREADS
431 : 305963 : fstat_result = _Py_fstat_noraise(self->fd, &fdfstat);
432 : 305963 : Py_END_ALLOW_THREADS
433 [ + + ]: 305963 : if (fstat_result < 0) {
434 : : /* Tolerate fstat() errors other than EBADF. See Issue #25717, where
435 : : an anonymous file on a Virtual Box shared folder filesystem would
436 : : raise ENOENT. */
437 : : #ifdef MS_WINDOWS
438 : : if (GetLastError() == ERROR_INVALID_HANDLE) {
439 : : PyErr_SetFromWindowsErr(0);
440 : : #else
441 [ + - ]: 2 : if (errno == EBADF) {
442 : 2 : PyErr_SetFromErrno(PyExc_OSError);
443 : : #endif
444 : 2 : goto error;
445 : : }
446 : : }
447 : : else {
448 : : #if defined(S_ISDIR) && defined(EISDIR)
449 : : /* On Unix, open will succeed for directories.
450 : : In Python, there should be no file objects referring to
451 : : directories, so we need a check. */
452 [ + + ]: 305961 : if (S_ISDIR(fdfstat.st_mode)) {
453 : 40 : errno = EISDIR;
454 : 40 : PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, nameobj);
455 : 40 : goto error;
456 : : }
457 : : #endif /* defined(S_ISDIR) */
458 : : #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
459 [ + - ]: 305921 : if (fdfstat.st_blksize > 1)
460 : 305921 : self->blksize = fdfstat.st_blksize;
461 : : #endif /* HAVE_STRUCT_STAT_ST_BLKSIZE */
462 : : }
463 : :
464 : : #if defined(MS_WINDOWS) || defined(__CYGWIN__)
465 : : /* don't translate newlines (\r\n <=> \n) */
466 : : _setmode(self->fd, O_BINARY);
467 : : #endif
468 : :
469 [ + + ]: 305921 : if (PyObject_SetAttr((PyObject *)self, &_Py_ID(name), nameobj) < 0)
470 : 1 : goto error;
471 : :
472 [ + + ]: 305920 : if (self->appending) {
473 : : /* For consistent behaviour, we explicitly seek to the
474 : : end of file (otherwise, it might be done only on the
475 : : first write()). */
476 : 1177 : PyObject *pos = portable_lseek(self, NULL, 2, true);
477 [ - + ]: 1177 : if (pos == NULL)
478 : 0 : goto error;
479 : 1177 : Py_DECREF(pos);
480 : : }
481 : :
482 : 305920 : goto done;
483 : :
484 : 8719 : error:
485 : 8719 : ret = -1;
486 [ + + ]: 8719 : if (!fd_is_own)
487 : 24 : self->fd = -1;
488 [ + + ]: 8719 : if (self->fd >= 0)
489 : 39 : internal_close(self);
490 : :
491 : 8680 : done:
492 : : #ifdef MS_WINDOWS
493 : : PyMem_Free(widename);
494 : : #endif
495 [ + + ]: 314639 : Py_CLEAR(stringobj);
496 : 314639 : return ret;
497 : : }
498 : :
499 : : static int
500 : 196633 : fileio_traverse(fileio *self, visitproc visit, void *arg)
501 : : {
502 [ + + - + ]: 196633 : Py_VISIT(self->dict);
503 : 196633 : return 0;
504 : : }
505 : :
506 : : static int
507 : 49 : fileio_clear(fileio *self)
508 : : {
509 [ + - ]: 49 : Py_CLEAR(self->dict);
510 : 49 : return 0;
511 : : }
512 : :
513 : : static void
514 : 314499 : fileio_dealloc(fileio *self)
515 : : {
516 : 314499 : self->finalizing = 1;
517 [ + + ]: 314499 : if (_PyIOBase_finalize((PyObject *) self) < 0)
518 : 4 : return;
519 : 314495 : _PyObject_GC_UNTRACK(self);
520 [ + + ]: 314495 : if (self->weakreflist != NULL)
521 : 1 : PyObject_ClearWeakRefs((PyObject *) self);
522 [ + + ]: 314495 : Py_CLEAR(self->dict);
523 : 314495 : Py_TYPE(self)->tp_free((PyObject *)self);
524 : : }
525 : :
526 : : static PyObject *
527 : 78 : err_closed(void)
528 : : {
529 : 78 : PyErr_SetString(PyExc_ValueError, "I/O operation on closed file");
530 : 78 : return NULL;
531 : : }
532 : :
533 : : static PyObject *
534 : 10 : err_mode(const char *action)
535 : : {
536 : 10 : _PyIO_State *state = IO_STATE();
537 [ + - ]: 10 : if (state != NULL)
538 : 10 : PyErr_Format(state->unsupported_operation,
539 : : "File not open for %s", action);
540 : 10 : return NULL;
541 : : }
542 : :
543 : : /*[clinic input]
544 : : _io.FileIO.fileno
545 : :
546 : : Return the underlying file descriptor (an integer).
547 : : [clinic start generated code]*/
548 : :
549 : : static PyObject *
550 : 63705 : _io_FileIO_fileno_impl(fileio *self)
551 : : /*[clinic end generated code: output=a9626ce5398ece90 input=0b9b2de67335ada3]*/
552 : : {
553 [ + + ]: 63705 : if (self->fd < 0)
554 : 18 : return err_closed();
555 : 63687 : return PyLong_FromLong((long) self->fd);
556 : : }
557 : :
558 : : /*[clinic input]
559 : : _io.FileIO.readable
560 : :
561 : : True if file was opened in a read mode.
562 : : [clinic start generated code]*/
563 : :
564 : : static PyObject *
565 : 268501 : _io_FileIO_readable_impl(fileio *self)
566 : : /*[clinic end generated code: output=640744a6150fe9ba input=a3fdfed6eea721c5]*/
567 : : {
568 [ + + ]: 268501 : if (self->fd < 0)
569 : 1 : return err_closed();
570 : 268500 : return PyBool_FromLong((long) self->readable);
571 : : }
572 : :
573 : : /*[clinic input]
574 : : _io.FileIO.writable
575 : :
576 : : True if file was opened in a write mode.
577 : : [clinic start generated code]*/
578 : :
579 : : static PyObject *
580 : 61927 : _io_FileIO_writable_impl(fileio *self)
581 : : /*[clinic end generated code: output=96cefc5446e89977 input=c204a808ca2e1748]*/
582 : : {
583 [ + + ]: 61927 : if (self->fd < 0)
584 : 1 : return err_closed();
585 : 61926 : return PyBool_FromLong((long) self->writable);
586 : : }
587 : :
588 : : /*[clinic input]
589 : : _io.FileIO.seekable
590 : :
591 : : True if file supports random-access.
592 : : [clinic start generated code]*/
593 : :
594 : : static PyObject *
595 : 83936 : _io_FileIO_seekable_impl(fileio *self)
596 : : /*[clinic end generated code: output=47909ca0a42e9287 input=c8e5554d2fd63c7f]*/
597 : : {
598 [ + + ]: 83936 : if (self->fd < 0)
599 : 1 : return err_closed();
600 [ + + ]: 83935 : if (self->seekable < 0) {
601 : : /* portable_lseek() sets the seekable attribute */
602 : 5169 : PyObject *pos = portable_lseek(self, NULL, SEEK_CUR, false);
603 : : assert(self->seekable >= 0);
604 [ + + ]: 5169 : if (pos == NULL) {
605 : 69 : PyErr_Clear();
606 : : }
607 : : else {
608 : 5100 : Py_DECREF(pos);
609 : : }
610 : : }
611 : 83935 : return PyBool_FromLong((long) self->seekable);
612 : : }
613 : :
614 : : /*[clinic input]
615 : : _io.FileIO.readinto
616 : : buffer: Py_buffer(accept={rwbuffer})
617 : : /
618 : :
619 : : Same as RawIOBase.readinto().
620 : : [clinic start generated code]*/
621 : :
622 : : static PyObject *
623 : 171616 : _io_FileIO_readinto_impl(fileio *self, Py_buffer *buffer)
624 : : /*[clinic end generated code: output=b01a5a22c8415cb4 input=4721d7b68b154eaf]*/
625 : : {
626 : : Py_ssize_t n;
627 : : int err;
628 : :
629 [ + + ]: 171616 : if (self->fd < 0)
630 : 4 : return err_closed();
631 [ - + ]: 171612 : if (!self->readable)
632 : 0 : return err_mode("reading");
633 : :
634 : 171612 : n = _Py_read(self->fd, buffer->buf, buffer->len);
635 : : /* copy errno because PyBuffer_Release() can indirectly modify it */
636 : 171607 : err = errno;
637 : :
638 [ + + ]: 171607 : if (n == -1) {
639 [ - + ]: 1 : if (err == EAGAIN) {
640 : 0 : PyErr_Clear();
641 : 0 : Py_RETURN_NONE;
642 : : }
643 : 1 : return NULL;
644 : : }
645 : :
646 : 171606 : return PyLong_FromSsize_t(n);
647 : : }
648 : :
649 : : static size_t
650 : 229 : new_buffersize(fileio *self, size_t currentsize)
651 : : {
652 : : size_t addend;
653 : :
654 : : /* Expand the buffer by an amount proportional to the current size,
655 : : giving us amortized linear-time behavior. For bigger sizes, use a
656 : : less-than-double growth factor to avoid excessive allocation. */
657 : : assert(currentsize <= PY_SSIZE_T_MAX);
658 [ + + ]: 229 : if (currentsize > 65536)
659 : 171 : addend = currentsize >> 3;
660 : : else
661 : 58 : addend = 256 + currentsize;
662 [ - + ]: 229 : if (addend < SMALLCHUNK)
663 : : /* Avoid tiny read() calls. */
664 : 0 : addend = SMALLCHUNK;
665 : 229 : return addend + currentsize;
666 : : }
667 : :
668 : : /*[clinic input]
669 : : _io.FileIO.readall
670 : :
671 : : Read all data from the file, returned as bytes.
672 : :
673 : : In non-blocking mode, returns as much as is immediately available,
674 : : or None if no data is available. Return an empty bytes object at EOF.
675 : : [clinic start generated code]*/
676 : :
677 : : static PyObject *
678 : 180774 : _io_FileIO_readall_impl(fileio *self)
679 : : /*[clinic end generated code: output=faa0292b213b4022 input=dbdc137f55602834]*/
680 : : {
681 : : struct _Py_stat_struct status;
682 : : Py_off_t pos, end;
683 : : PyObject *result;
684 : 180774 : Py_ssize_t bytes_read = 0;
685 : : Py_ssize_t n;
686 : : size_t bufsize;
687 : : int fstat_result;
688 : :
689 [ + + ]: 180774 : if (self->fd < 0)
690 : 4 : return err_closed();
691 : :
692 : 180770 : Py_BEGIN_ALLOW_THREADS
693 : : _Py_BEGIN_SUPPRESS_IPH
694 : : #ifdef MS_WINDOWS
695 : : pos = _lseeki64(self->fd, 0L, SEEK_CUR);
696 : : #else
697 : 180770 : pos = lseek(self->fd, 0L, SEEK_CUR);
698 : : #endif
699 : : _Py_END_SUPPRESS_IPH
700 : 180770 : fstat_result = _Py_fstat_noraise(self->fd, &status);
701 : 180770 : Py_END_ALLOW_THREADS
702 : :
703 [ + + ]: 180770 : if (fstat_result == 0)
704 : 180769 : end = status.st_size;
705 : : else
706 : 1 : end = (Py_off_t)-1;
707 : :
708 [ + + + + : 180770 : if (end > 0 && end >= pos && pos >= 0 && end - pos < PY_SSIZE_T_MAX) {
+ - + - ]
709 : : /* This is probably a real file, so we try to allocate a
710 : : buffer one byte larger than the rest of the file. If the
711 : : calculation is right then we should get EOF without having
712 : : to enlarge the buffer. */
713 : 179787 : bufsize = (size_t)(end - pos + 1);
714 : : } else {
715 : 983 : bufsize = SMALLCHUNK;
716 : : }
717 : :
718 : 180770 : result = PyBytes_FromStringAndSize(NULL, bufsize);
719 [ - + ]: 180770 : if (result == NULL)
720 : 0 : return NULL;
721 : :
722 : : while (1) {
723 [ + + ]: 362205 : if (bytes_read >= (Py_ssize_t)bufsize) {
724 : 229 : bufsize = new_buffersize(self, bytes_read);
725 [ + - - + ]: 229 : if (bufsize > PY_SSIZE_T_MAX || bufsize <= 0) {
726 : 0 : PyErr_SetString(PyExc_OverflowError,
727 : : "unbounded read returned more bytes "
728 : : "than a Python bytes object can hold");
729 : 0 : Py_DECREF(result);
730 : 0 : return NULL;
731 : : }
732 : :
733 [ + - ]: 229 : if (PyBytes_GET_SIZE(result) < (Py_ssize_t)bufsize) {
734 [ - + ]: 229 : if (_PyBytes_Resize(&result, bufsize) < 0)
735 : 0 : return NULL;
736 : : }
737 : : }
738 : :
739 : 724410 : n = _Py_read(self->fd,
740 : 362205 : PyBytes_AS_STRING(result) + bytes_read,
741 : : bufsize - bytes_read);
742 : :
743 [ + + ]: 362205 : if (n == 0)
744 : 180759 : break;
745 [ + + ]: 181446 : if (n == -1) {
746 [ + + ]: 11 : if (errno == EAGAIN) {
747 : 10 : PyErr_Clear();
748 [ + + ]: 10 : if (bytes_read > 0)
749 : 8 : break;
750 : 2 : Py_DECREF(result);
751 : 2 : Py_RETURN_NONE;
752 : : }
753 : 1 : Py_DECREF(result);
754 : 1 : return NULL;
755 : : }
756 : 181435 : bytes_read += n;
757 : 181435 : pos += n;
758 : : }
759 : :
760 [ + - ]: 180767 : if (PyBytes_GET_SIZE(result) > bytes_read) {
761 [ - + ]: 180767 : if (_PyBytes_Resize(&result, bytes_read) < 0)
762 : 0 : return NULL;
763 : : }
764 : 180767 : return result;
765 : : }
766 : :
767 : : /*[clinic input]
768 : : _io.FileIO.read
769 : : size: Py_ssize_t(accept={int, NoneType}) = -1
770 : : /
771 : :
772 : : Read at most size bytes, returned as bytes.
773 : :
774 : : Only makes one system call, so less data may be returned than requested.
775 : : In non-blocking mode, returns None if no data is available.
776 : : Return an empty bytes object at EOF.
777 : : [clinic start generated code]*/
778 : :
779 : : static PyObject *
780 : 605 : _io_FileIO_read_impl(fileio *self, Py_ssize_t size)
781 : : /*[clinic end generated code: output=42528d39dd0ca641 input=bec9a2c704ddcbc9]*/
782 : : {
783 : : char *ptr;
784 : : Py_ssize_t n;
785 : : PyObject *bytes;
786 : :
787 [ + + ]: 605 : if (self->fd < 0)
788 : 11 : return err_closed();
789 [ + + ]: 594 : if (!self->readable)
790 : 5 : return err_mode("reading");
791 : :
792 [ + + ]: 589 : if (size < 0)
793 : 153 : return _io_FileIO_readall_impl(self);
794 : :
795 : : if (size > _PY_READ_MAX) {
796 : : size = _PY_READ_MAX;
797 : : }
798 : :
799 : 436 : bytes = PyBytes_FromStringAndSize(NULL, size);
800 [ - + ]: 436 : if (bytes == NULL)
801 : 0 : return NULL;
802 : 436 : ptr = PyBytes_AS_STRING(bytes);
803 : :
804 : 436 : n = _Py_read(self->fd, ptr, size);
805 [ + + ]: 436 : if (n == -1) {
806 : : /* copy errno because Py_DECREF() can indirectly modify it */
807 : 1 : int err = errno;
808 : 1 : Py_DECREF(bytes);
809 [ - + ]: 1 : if (err == EAGAIN) {
810 : 0 : PyErr_Clear();
811 : 0 : Py_RETURN_NONE;
812 : : }
813 : 1 : return NULL;
814 : : }
815 : :
816 [ + + ]: 435 : if (n != size) {
817 [ - + ]: 14 : if (_PyBytes_Resize(&bytes, n) < 0) {
818 [ # # ]: 0 : Py_CLEAR(bytes);
819 : 0 : return NULL;
820 : : }
821 : : }
822 : :
823 : 435 : return (PyObject *) bytes;
824 : : }
825 : :
826 : : /*[clinic input]
827 : : _io.FileIO.write
828 : : b: Py_buffer
829 : : /
830 : :
831 : : Write buffer b to file, return number of bytes written.
832 : :
833 : : Only makes one system call, so not all of the data may be written.
834 : : The number of bytes actually written is returned. In non-blocking mode,
835 : : returns None if the write would block.
836 : : [clinic start generated code]*/
837 : :
838 : : static PyObject *
839 : 292276 : _io_FileIO_write_impl(fileio *self, Py_buffer *b)
840 : : /*[clinic end generated code: output=b4059db3d363a2f7 input=6e7908b36f0ce74f]*/
841 : : {
842 : : Py_ssize_t n;
843 : : int err;
844 : :
845 [ + + ]: 292276 : if (self->fd < 0)
846 : 4 : return err_closed();
847 [ + + ]: 292272 : if (!self->writable)
848 : 3 : return err_mode("writing");
849 : :
850 : 292269 : n = _Py_write(self->fd, b->buf, b->len);
851 : : /* copy errno because PyBuffer_Release() can indirectly modify it */
852 : 292269 : err = errno;
853 : :
854 [ + + ]: 292269 : if (n < 0) {
855 [ + + ]: 19 : if (err == EAGAIN) {
856 : 7 : PyErr_Clear();
857 : 7 : Py_RETURN_NONE;
858 : : }
859 : 12 : return NULL;
860 : : }
861 : :
862 : 292250 : return PyLong_FromSsize_t(n);
863 : : }
864 : :
865 : : /* XXX Windows support below is likely incomplete */
866 : :
867 : : /* Cribbed from posix_lseek() */
868 : : static PyObject *
869 : 408405 : portable_lseek(fileio *self, PyObject *posobj, int whence, bool suppress_pipe_error)
870 : : {
871 : : Py_off_t pos, res;
872 : 408405 : int fd = self->fd;
873 : :
874 : : #ifdef SEEK_SET
875 : : /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
876 : : switch (whence) {
877 : : #if SEEK_SET != 0
878 : : case 0: whence = SEEK_SET; break;
879 : : #endif
880 : : #if SEEK_CUR != 1
881 : : case 1: whence = SEEK_CUR; break;
882 : : #endif
883 : : #if SEEK_END != 2
884 : : case 2: whence = SEEK_END; break;
885 : : #endif
886 : : }
887 : : #endif /* SEEK_SET */
888 : :
889 [ + + ]: 408405 : if (posobj == NULL) {
890 : 355801 : pos = 0;
891 : : }
892 : : else {
893 : : #if defined(HAVE_LARGEFILE_SUPPORT)
894 : : pos = PyLong_AsLongLong(posobj);
895 : : #else
896 : 52604 : pos = PyLong_AsLong(posobj);
897 : : #endif
898 [ + + ]: 52604 : if (PyErr_Occurred())
899 : 2 : return NULL;
900 : : }
901 : :
902 : 408403 : Py_BEGIN_ALLOW_THREADS
903 : : _Py_BEGIN_SUPPRESS_IPH
904 : : #ifdef MS_WINDOWS
905 : : res = _lseeki64(fd, pos, whence);
906 : : #else
907 : 408403 : res = lseek(fd, pos, whence);
908 : : #endif
909 : : _Py_END_SUPPRESS_IPH
910 : 408403 : Py_END_ALLOW_THREADS
911 : :
912 [ + + ]: 408403 : if (self->seekable < 0) {
913 : 297464 : self->seekable = (res >= 0);
914 : : }
915 : :
916 [ + + ]: 408403 : if (res < 0) {
917 [ + + + - ]: 17303 : if (suppress_pipe_error && errno == ESPIPE) {
918 : 1 : res = 0;
919 : : } else {
920 : 17302 : return PyErr_SetFromErrno(PyExc_OSError);
921 : : }
922 : : }
923 : :
924 : : #if defined(HAVE_LARGEFILE_SUPPORT)
925 : : return PyLong_FromLongLong(res);
926 : : #else
927 : 391101 : return PyLong_FromLong(res);
928 : : #endif
929 : : }
930 : :
931 : : /*[clinic input]
932 : : _io.FileIO.seek
933 : : pos: object
934 : : whence: int = 0
935 : : /
936 : :
937 : : Move to new file position and return the file position.
938 : :
939 : : Argument offset is a byte count. Optional argument whence defaults to
940 : : SEEK_SET or 0 (offset from start of file, offset should be >= 0); other values
941 : : are SEEK_CUR or 1 (move relative to current position, positive or negative),
942 : : and SEEK_END or 2 (move relative to end of file, usually negative, although
943 : : many platforms allow seeking beyond the end of a file).
944 : :
945 : : Note that not all file objects are seekable.
946 : : [clinic start generated code]*/
947 : :
948 : : static PyObject *
949 : 52608 : _io_FileIO_seek_impl(fileio *self, PyObject *pos, int whence)
950 : : /*[clinic end generated code: output=c976acdf054e6655 input=0439194b0774d454]*/
951 : : {
952 [ + + ]: 52608 : if (self->fd < 0)
953 : 4 : return err_closed();
954 : :
955 : 52604 : return portable_lseek(self, pos, whence, false);
956 : : }
957 : :
958 : : /*[clinic input]
959 : : _io.FileIO.tell
960 : :
961 : : Current file position.
962 : :
963 : : Can raise OSError for non seekable files.
964 : : [clinic start generated code]*/
965 : :
966 : : static PyObject *
967 : 349412 : _io_FileIO_tell_impl(fileio *self)
968 : : /*[clinic end generated code: output=ffe2147058809d0b input=807e24ead4cec2f9]*/
969 : : {
970 [ + + ]: 349412 : if (self->fd < 0)
971 : 9 : return err_closed();
972 : :
973 : 349403 : return portable_lseek(self, NULL, 1, false);
974 : : }
975 : :
976 : : #ifdef HAVE_FTRUNCATE
977 : : /*[clinic input]
978 : : _io.FileIO.truncate
979 : : size as posobj: object = None
980 : : /
981 : :
982 : : Truncate the file to at most size bytes and return the truncated size.
983 : :
984 : : Size defaults to the current file position, as returned by tell().
985 : : The current file position is changed to the value of size.
986 : : [clinic start generated code]*/
987 : :
988 : : static PyObject *
989 : 114 : _io_FileIO_truncate_impl(fileio *self, PyObject *posobj)
990 : : /*[clinic end generated code: output=e49ca7a916c176fa input=b0ac133939823875]*/
991 : : {
992 : : Py_off_t pos;
993 : : int ret;
994 : : int fd;
995 : :
996 : 114 : fd = self->fd;
997 [ + + ]: 114 : if (fd < 0)
998 : 4 : return err_closed();
999 [ + + ]: 110 : if (!self->writable)
1000 : 2 : return err_mode("writing");
1001 : :
1002 [ + + ]: 108 : if (posobj == Py_None) {
1003 : : /* Get the current position. */
1004 : 52 : posobj = portable_lseek(self, NULL, 1, false);
1005 [ + + ]: 52 : if (posobj == NULL)
1006 : 1 : return NULL;
1007 : : }
1008 : : else {
1009 : 56 : Py_INCREF(posobj);
1010 : : }
1011 : :
1012 : : #if defined(HAVE_LARGEFILE_SUPPORT)
1013 : : pos = PyLong_AsLongLong(posobj);
1014 : : #else
1015 : 107 : pos = PyLong_AsLong(posobj);
1016 : : #endif
1017 [ - + ]: 107 : if (PyErr_Occurred()){
1018 : 0 : Py_DECREF(posobj);
1019 : 0 : return NULL;
1020 : : }
1021 : :
1022 : 107 : Py_BEGIN_ALLOW_THREADS
1023 : : _Py_BEGIN_SUPPRESS_IPH
1024 : 107 : errno = 0;
1025 : : #ifdef MS_WINDOWS
1026 : : ret = _chsize_s(fd, pos);
1027 : : #else
1028 : 107 : ret = ftruncate(fd, pos);
1029 : : #endif
1030 : : _Py_END_SUPPRESS_IPH
1031 : 107 : Py_END_ALLOW_THREADS
1032 : :
1033 [ + + ]: 107 : if (ret != 0) {
1034 : 2 : Py_DECREF(posobj);
1035 : 2 : PyErr_SetFromErrno(PyExc_OSError);
1036 : 2 : return NULL;
1037 : : }
1038 : :
1039 : 105 : return posobj;
1040 : : }
1041 : : #endif /* HAVE_FTRUNCATE */
1042 : :
1043 : : static const char *
1044 : 325 : mode_string(fileio *self)
1045 : : {
1046 [ + + ]: 325 : if (self->created) {
1047 [ - + ]: 14 : if (self->readable)
1048 : 0 : return "xb+";
1049 : : else
1050 : 14 : return "xb";
1051 : : }
1052 [ + + ]: 311 : if (self->appending) {
1053 [ + + ]: 5 : if (self->readable)
1054 : 2 : return "ab+";
1055 : : else
1056 : 3 : return "ab";
1057 : : }
1058 [ + + ]: 306 : else if (self->readable) {
1059 [ + + ]: 193 : if (self->writable)
1060 : 11 : return "rb+";
1061 : : else
1062 : 182 : return "rb";
1063 : : }
1064 : : else
1065 : 113 : return "wb";
1066 : : }
1067 : :
1068 : : static PyObject *
1069 : 17 : fileio_repr(fileio *self)
1070 : : {
1071 : : PyObject *nameobj, *res;
1072 : :
1073 [ + + ]: 17 : if (self->fd < 0)
1074 : 1 : return PyUnicode_FromFormat("<_io.FileIO [closed]>");
1075 : :
1076 [ - + ]: 16 : if (_PyObject_LookupAttr((PyObject *) self, &_Py_ID(name), &nameobj) < 0) {
1077 : 0 : return NULL;
1078 : : }
1079 [ + + ]: 16 : if (nameobj == NULL) {
1080 : 1 : res = PyUnicode_FromFormat(
1081 : : "<_io.FileIO fd=%d mode='%s' closefd=%s>",
1082 [ + - ]: 1 : self->fd, mode_string(self), self->closefd ? "True" : "False");
1083 : : }
1084 : : else {
1085 : 15 : int status = Py_ReprEnter((PyObject *)self);
1086 : 15 : res = NULL;
1087 [ + + ]: 15 : if (status == 0) {
1088 : 14 : res = PyUnicode_FromFormat(
1089 : : "<_io.FileIO name=%R mode='%s' closefd=%s>",
1090 [ + + ]: 14 : nameobj, mode_string(self), self->closefd ? "True" : "False");
1091 : 14 : Py_ReprLeave((PyObject *)self);
1092 : : }
1093 [ + - ]: 1 : else if (status > 0) {
1094 : 1 : PyErr_Format(PyExc_RuntimeError,
1095 : : "reentrant call inside %s.__repr__",
1096 : 1 : Py_TYPE(self)->tp_name);
1097 : : }
1098 : 15 : Py_DECREF(nameobj);
1099 : : }
1100 : 16 : return res;
1101 : : }
1102 : :
1103 : : /*[clinic input]
1104 : : _io.FileIO.isatty
1105 : :
1106 : : True if the file is connected to a TTY device.
1107 : : [clinic start generated code]*/
1108 : :
1109 : : static PyObject *
1110 : 305860 : _io_FileIO_isatty_impl(fileio *self)
1111 : : /*[clinic end generated code: output=932c39924e9a8070 input=cd94ca1f5e95e843]*/
1112 : : {
1113 : : long res;
1114 : :
1115 [ + + ]: 305860 : if (self->fd < 0)
1116 : 17 : return err_closed();
1117 : 305843 : Py_BEGIN_ALLOW_THREADS
1118 : : _Py_BEGIN_SUPPRESS_IPH
1119 : 305843 : res = isatty(self->fd);
1120 : : _Py_END_SUPPRESS_IPH
1121 : 305843 : Py_END_ALLOW_THREADS
1122 : 305843 : return PyBool_FromLong(res);
1123 : : }
1124 : :
1125 : : #include "clinic/fileio.c.h"
1126 : :
1127 : : static PyMethodDef fileio_methods[] = {
1128 : : _IO_FILEIO_READ_METHODDEF
1129 : : _IO_FILEIO_READALL_METHODDEF
1130 : : _IO_FILEIO_READINTO_METHODDEF
1131 : : _IO_FILEIO_WRITE_METHODDEF
1132 : : _IO_FILEIO_SEEK_METHODDEF
1133 : : _IO_FILEIO_TELL_METHODDEF
1134 : : _IO_FILEIO_TRUNCATE_METHODDEF
1135 : : _IO_FILEIO_CLOSE_METHODDEF
1136 : : _IO_FILEIO_SEEKABLE_METHODDEF
1137 : : _IO_FILEIO_READABLE_METHODDEF
1138 : : _IO_FILEIO_WRITABLE_METHODDEF
1139 : : _IO_FILEIO_FILENO_METHODDEF
1140 : : _IO_FILEIO_ISATTY_METHODDEF
1141 : : {"_dealloc_warn", (PyCFunction)fileio_dealloc_warn, METH_O, NULL},
1142 : : {NULL, NULL} /* sentinel */
1143 : : };
1144 : :
1145 : : /* 'closed' and 'mode' are attributes for backwards compatibility reasons. */
1146 : :
1147 : : static PyObject *
1148 : 1390574 : get_closed(fileio *self, void *closure)
1149 : : {
1150 : 1390574 : return PyBool_FromLong((long)(self->fd < 0));
1151 : : }
1152 : :
1153 : : static PyObject *
1154 : 2 : get_closefd(fileio *self, void *closure)
1155 : : {
1156 : 2 : return PyBool_FromLong((long)(self->closefd));
1157 : : }
1158 : :
1159 : : static PyObject *
1160 : 310 : get_mode(fileio *self, void *closure)
1161 : : {
1162 : 310 : return PyUnicode_FromString(mode_string(self));
1163 : : }
1164 : :
1165 : : static PyGetSetDef fileio_getsetlist[] = {
1166 : : {"closed", (getter)get_closed, NULL, "True if the file is closed"},
1167 : : {"closefd", (getter)get_closefd, NULL,
1168 : : "True if the file descriptor will be closed by close()."},
1169 : : {"mode", (getter)get_mode, NULL, "String giving the file mode"},
1170 : : {NULL},
1171 : : };
1172 : :
1173 : : static PyMemberDef fileio_members[] = {
1174 : : {"_blksize", T_UINT, offsetof(fileio, blksize), 0},
1175 : : {"_finalizing", T_BOOL, offsetof(fileio, finalizing), 0},
1176 : : {NULL}
1177 : : };
1178 : :
1179 : : PyTypeObject PyFileIO_Type = {
1180 : : PyVarObject_HEAD_INIT(NULL, 0)
1181 : : "_io.FileIO",
1182 : : sizeof(fileio),
1183 : : 0,
1184 : : (destructor)fileio_dealloc, /* tp_dealloc */
1185 : : 0, /* tp_vectorcall_offset */
1186 : : 0, /* tp_getattr */
1187 : : 0, /* tp_setattr */
1188 : : 0, /* tp_as_async */
1189 : : (reprfunc)fileio_repr, /* tp_repr */
1190 : : 0, /* tp_as_number */
1191 : : 0, /* tp_as_sequence */
1192 : : 0, /* tp_as_mapping */
1193 : : 0, /* tp_hash */
1194 : : 0, /* tp_call */
1195 : : 0, /* tp_str */
1196 : : PyObject_GenericGetAttr, /* tp_getattro */
1197 : : 0, /* tp_setattro */
1198 : : 0, /* tp_as_buffer */
1199 : : Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
1200 : : | Py_TPFLAGS_HAVE_GC, /* tp_flags */
1201 : : _io_FileIO___init____doc__, /* tp_doc */
1202 : : (traverseproc)fileio_traverse, /* tp_traverse */
1203 : : (inquiry)fileio_clear, /* tp_clear */
1204 : : 0, /* tp_richcompare */
1205 : : offsetof(fileio, weakreflist), /* tp_weaklistoffset */
1206 : : 0, /* tp_iter */
1207 : : 0, /* tp_iternext */
1208 : : fileio_methods, /* tp_methods */
1209 : : fileio_members, /* tp_members */
1210 : : fileio_getsetlist, /* tp_getset */
1211 : : 0, /* tp_base */
1212 : : 0, /* tp_dict */
1213 : : 0, /* tp_descr_get */
1214 : : 0, /* tp_descr_set */
1215 : : offsetof(fileio, dict), /* tp_dictoffset */
1216 : : _io_FileIO___init__, /* tp_init */
1217 : : PyType_GenericAlloc, /* tp_alloc */
1218 : : fileio_new, /* tp_new */
1219 : : PyObject_GC_Del, /* tp_free */
1220 : : 0, /* tp_is_gc */
1221 : : 0, /* tp_bases */
1222 : : 0, /* tp_mro */
1223 : : 0, /* tp_cache */
1224 : : 0, /* tp_subclasses */
1225 : : 0, /* tp_weaklist */
1226 : : 0, /* tp_del */
1227 : : 0, /* tp_version_tag */
1228 : : 0, /* tp_finalize */
1229 : : };
|