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