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