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