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