1 /* Author: Daniel Stutzbach */ 2 3 #define PY_SSIZE_T_CLEAN 4 #include "Python.h" 5 #ifdef HAVE_SYS_TYPES_H 6 #include <sys/types.h> 7 #endif 8 #ifdef HAVE_SYS_STAT_H 9 #include <sys/stat.h> 10 #endif 11 #ifdef HAVE_FCNTL_H 12 #include <fcntl.h> 13 #endif 14 #include <stddef.h> /* For offsetof */ 15 #include "_iomodule.h" 16 17 /* 18 * Known likely problems: 19 * 20 * - Files larger then 2**32-1 21 * - Files with unicode filenames 22 * - Passing numbers greater than 2**32-1 when an integer is expected 23 * - Making it work on Windows and other oddball platforms 24 * 25 * To Do: 26 * 27 * - autoconfify header file inclusion 28 */ 29 30 #ifdef MS_WINDOWS 31 /* can simulate truncate with Win32 API functions; see file_truncate */ 32 #define HAVE_FTRUNCATE 33 #define WIN32_LEAN_AND_MEAN 34 #include <windows.h> 35 #endif 36 37 #if BUFSIZ < (8*1024) 38 #define SMALLCHUNK (8*1024) 39 #elif (BUFSIZ >= (2 << 25)) 40 #error "unreasonable BUFSIZ > 64MB defined" 41 #else 42 #define SMALLCHUNK BUFSIZ 43 #endif 44 45 typedef struct { 46 PyObject_HEAD 47 int fd; 48 unsigned int readable : 1; 49 unsigned int writable : 1; 50 unsigned int appending : 1; 51 signed int seekable : 2; /* -1 means unknown */ 52 unsigned int closefd : 1; 53 PyObject *weakreflist; 54 PyObject *dict; 55 } fileio; 56 57 PyTypeObject PyFileIO_Type; 58 59 #define PyFileIO_Check(op) (PyObject_TypeCheck((op), &PyFileIO_Type)) 60 61 int 62 _PyFileIO_closed(PyObject *self) 63 { 64 return ((fileio *)self)->fd < 0; 65 } 66 67 static PyObject * 68 portable_lseek(int fd, PyObject *posobj, int whence); 69 70 static PyObject *portable_lseek(int fd, PyObject *posobj, int whence); 71 72 /* Returns 0 on success, -1 with exception set on failure. */ 73 static int 74 internal_close(fileio *self) 75 { 76 int err = 0; 77 int save_errno = 0; 78 if (self->fd >= 0) { 79 int fd = self->fd; 80 self->fd = -1; 81 /* fd is accessible and someone else may have closed it */ 82 if (_PyVerify_fd(fd)) { 83 Py_BEGIN_ALLOW_THREADS 84 err = close(fd); 85 if (err < 0) 86 save_errno = errno; 87 Py_END_ALLOW_THREADS 88 } else { 89 save_errno = errno; 90 err = -1; 91 } 92 } 93 if (err < 0) { 94 errno = save_errno; 95 PyErr_SetFromErrno(PyExc_IOError); 96 return -1; 97 } 98 return 0; 99 } 100 101 static PyObject * 102 fileio_close(fileio *self) 103 { 104 PyObject *res; 105 res = PyObject_CallMethod((PyObject*)&PyRawIOBase_Type, 106 "close", "O", self); 107 if (!self->closefd) { 108 self->fd = -1; 109 return res; 110 } 111 if (internal_close(self) < 0) 112 Py_CLEAR(res); 113 return res; 114 } 115 116 static PyObject * 117 fileio_new(PyTypeObject *type, PyObject *args, PyObject *kwds) 118 { 119 fileio *self; 120 121 assert(type != NULL && type->tp_alloc != NULL); 122 123 self = (fileio *) type->tp_alloc(type, 0); 124 if (self != NULL) { 125 self->fd = -1; 126 self->readable = 0; 127 self->writable = 0; 128 self->appending = 0; 129 self->seekable = -1; 130 self->closefd = 1; 131 self->weakreflist = NULL; 132 } 133 134 return (PyObject *) self; 135 } 136 137 /* On Unix, open will succeed for directories. 138 In Python, there should be no file objects referring to 139 directories, so we need a check. */ 140 141 static int 142 dircheck(fileio* self, PyObject *nameobj) 143 { 144 #if defined(HAVE_FSTAT) && defined(S_IFDIR) && defined(EISDIR) 145 struct stat buf; 146 if (self->fd < 0) 147 return 0; 148 if (fstat(self->fd, &buf) == 0 && S_ISDIR(buf.st_mode)) { 149 errno = EISDIR; 150 PyErr_SetFromErrnoWithFilenameObject(PyExc_IOError, nameobj); 151 return -1; 152 } 153 #endif 154 return 0; 155 } 156 157 static int 158 check_fd(int fd) 159 { 160 #if defined(HAVE_FSTAT) 161 struct stat buf; 162 if (!_PyVerify_fd(fd) || (fstat(fd, &buf) < 0 && errno == EBADF)) { 163 PyObject *exc; 164 char *msg = strerror(EBADF); 165 exc = PyObject_CallFunction(PyExc_OSError, "(is)", 166 EBADF, msg); 167 PyErr_SetObject(PyExc_OSError, exc); 168 Py_XDECREF(exc); 169 return -1; 170 } 171 #endif 172 return 0; 173 } 174 175 176 static int 177 fileio_init(PyObject *oself, PyObject *args, PyObject *kwds) 178 { 179 fileio *self = (fileio *) oself; 180 static char *kwlist[] = {"file", "mode", "closefd", NULL}; 181 const char *name = NULL; 182 PyObject *nameobj, *stringobj = NULL; 183 char *mode = "r"; 184 char *s; 185 #ifdef MS_WINDOWS 186 Py_UNICODE *widename = NULL; 187 #endif 188 int ret = 0; 189 int rwa = 0, plus = 0; 190 int flags = 0; 191 int fd = -1; 192 int closefd = 1; 193 int fd_is_own = 0; 194 195 assert(PyFileIO_Check(oself)); 196 if (self->fd >= 0) { 197 if (self->closefd) { 198 /* Have to close the existing file first. */ 199 if (internal_close(self) < 0) 200 return -1; 201 } 202 else 203 self->fd = -1; 204 } 205 206 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|si:fileio", 207 kwlist, &nameobj, &mode, &closefd)) 208 return -1; 209 210 if (PyFloat_Check(nameobj)) { 211 PyErr_SetString(PyExc_TypeError, 212 "integer argument expected, got float"); 213 return -1; 214 } 215 216 fd = _PyLong_AsInt(nameobj); 217 if (fd < 0) { 218 if (!PyErr_Occurred()) { 219 PyErr_SetString(PyExc_ValueError, 220 "negative file descriptor"); 221 return -1; 222 } 223 PyErr_Clear(); 224 } 225 226 #ifdef MS_WINDOWS 227 if (PyUnicode_Check(nameobj)) 228 widename = PyUnicode_AS_UNICODE(nameobj); 229 if (widename == NULL) 230 #endif 231 if (fd < 0) 232 { 233 if (PyBytes_Check(nameobj) || PyByteArray_Check(nameobj)) { 234 Py_ssize_t namelen; 235 if (PyObject_AsCharBuffer(nameobj, &name, &namelen) < 0) 236 return -1; 237 } 238 else { 239 PyObject *u = PyUnicode_FromObject(nameobj); 240 241 if (u == NULL) 242 return -1; 243 244 stringobj = PyUnicode_AsEncodedString( 245 u, Py_FileSystemDefaultEncoding, NULL); 246 Py_DECREF(u); 247 if (stringobj == NULL) 248 return -1; 249 if (!PyBytes_Check(stringobj)) { 250 PyErr_SetString(PyExc_TypeError, 251 "encoder failed to return bytes"); 252 goto error; 253 } 254 name = PyBytes_AS_STRING(stringobj); 255 } 256 } 257 258 s = mode; 259 while (*s) { 260 switch (*s++) { 261 case 'r': 262 if (rwa) { 263 bad_mode: 264 PyErr_SetString(PyExc_ValueError, 265 "Must have exactly one of read/write/append " 266 "mode and at most one plus"); 267 goto error; 268 } 269 rwa = 1; 270 self->readable = 1; 271 break; 272 case 'w': 273 if (rwa) 274 goto bad_mode; 275 rwa = 1; 276 self->writable = 1; 277 flags |= O_CREAT | O_TRUNC; 278 break; 279 case 'a': 280 if (rwa) 281 goto bad_mode; 282 rwa = 1; 283 self->writable = 1; 284 self->appending = 1; 285 flags |= O_APPEND | O_CREAT; 286 break; 287 case 'b': 288 break; 289 case '+': 290 if (plus) 291 goto bad_mode; 292 self->readable = self->writable = 1; 293 plus = 1; 294 break; 295 default: 296 PyErr_Format(PyExc_ValueError, 297 "invalid mode: %.200s", mode); 298 goto error; 299 } 300 } 301 302 if (!rwa) 303 goto bad_mode; 304 305 if (self->readable && self->writable) 306 flags |= O_RDWR; 307 else if (self->readable) 308 flags |= O_RDONLY; 309 else 310 flags |= O_WRONLY; 311 312 #ifdef O_BINARY 313 flags |= O_BINARY; 314 #endif 315 316 if (fd >= 0) { 317 if (check_fd(fd)) 318 goto error; 319 self->fd = fd; 320 self->closefd = closefd; 321 } 322 else { 323 self->closefd = 1; 324 if (!closefd) { 325 PyErr_SetString(PyExc_ValueError, 326 "Cannot use closefd=False with file name"); 327 goto error; 328 } 329 330 Py_BEGIN_ALLOW_THREADS 331 errno = 0; 332 #ifdef MS_WINDOWS 333 if (widename != NULL) 334 self->fd = _wopen(widename, flags, 0666); 335 else 336 #endif 337 self->fd = open(name, flags, 0666); 338 Py_END_ALLOW_THREADS 339 fd_is_own = 1; 340 if (self->fd < 0) { 341 #ifdef MS_WINDOWS 342 if (widename != NULL) 343 PyErr_SetFromErrnoWithUnicodeFilename(PyExc_IOError, widename); 344 else 345 #endif 346 PyErr_SetFromErrnoWithFilename(PyExc_IOError, name); 347 goto error; 348 } 349 } 350 if (dircheck(self, nameobj) < 0) 351 goto error; 352 353 if (PyObject_SetAttrString((PyObject *)self, "name", nameobj) < 0) 354 goto error; 355 356 if (self->appending) { 357 /* For consistent behaviour, we explicitly seek to the 358 end of file (otherwise, it might be done only on the 359 first write()). */ 360 PyObject *pos = portable_lseek(self->fd, NULL, 2); 361 if (pos == NULL) 362 goto error; 363 Py_DECREF(pos); 364 } 365 366 goto done; 367 368 error: 369 if (!fd_is_own) 370 self->fd = -1; 371 372 ret = -1; 373 374 done: 375 Py_CLEAR(stringobj); 376 return ret; 377 } 378 379 static int 380 fileio_traverse(fileio *self, visitproc visit, void *arg) 381 { 382 Py_VISIT(self->dict); 383 return 0; 384 } 385 386 static int 387 fileio_clear(fileio *self) 388 { 389 Py_CLEAR(self->dict); 390 return 0; 391 } 392 393 static void 394 fileio_dealloc(fileio *self) 395 { 396 if (_PyIOBase_finalize((PyObject *) self) < 0) 397 return; 398 _PyObject_GC_UNTRACK(self); 399 if (self->weakreflist != NULL) 400 PyObject_ClearWeakRefs((PyObject *) self); 401 Py_CLEAR(self->dict); 402 Py_TYPE(self)->tp_free((PyObject *)self); 403 } 404 405 static PyObject * 406 err_closed(void) 407 { 408 PyErr_SetString(PyExc_ValueError, "I/O operation on closed file"); 409 return NULL; 410 } 411 412 static PyObject * 413 err_mode(char *action) 414 { 415 PyErr_Format(PyExc_ValueError, "File not open for %s", action); 416 return NULL; 417 } 418 419 static PyObject * 420 fileio_fileno(fileio *self) 421 { 422 if (self->fd < 0) 423 return err_closed(); 424 return PyInt_FromLong((long) self->fd); 425 } 426 427 static PyObject * 428 fileio_readable(fileio *self) 429 { 430 if (self->fd < 0) 431 return err_closed(); 432 return PyBool_FromLong((long) self->readable); 433 } 434 435 static PyObject * 436 fileio_writable(fileio *self) 437 { 438 if (self->fd < 0) 439 return err_closed(); 440 return PyBool_FromLong((long) self->writable); 441 } 442 443 static PyObject * 444 fileio_seekable(fileio *self) 445 { 446 if (self->fd < 0) 447 return err_closed(); 448 if (self->seekable < 0) { 449 PyObject *pos = portable_lseek(self->fd, NULL, SEEK_CUR); 450 if (pos == NULL) { 451 PyErr_Clear(); 452 self->seekable = 0; 453 } else { 454 Py_DECREF(pos); 455 self->seekable = 1; 456 } 457 } 458 return PyBool_FromLong((long) self->seekable); 459 } 460 461 static PyObject * 462 fileio_readinto(fileio *self, PyObject *args) 463 { 464 Py_buffer pbuf; 465 Py_ssize_t n, len; 466 467 if (self->fd < 0) 468 return err_closed(); 469 if (!self->readable) 470 return err_mode("reading"); 471 472 if (!PyArg_ParseTuple(args, "w*", &pbuf)) 473 return NULL; 474 475 if (_PyVerify_fd(self->fd)) { 476 len = pbuf.len; 477 Py_BEGIN_ALLOW_THREADS 478 errno = 0; 479 #if defined(MS_WIN64) || defined(MS_WINDOWS) 480 if (len > INT_MAX) 481 len = INT_MAX; 482 n = read(self->fd, pbuf.buf, (int)len); 483 #else 484 n = read(self->fd, pbuf.buf, len); 485 #endif 486 Py_END_ALLOW_THREADS 487 } else 488 n = -1; 489 PyBuffer_Release(&pbuf); 490 if (n < 0) { 491 if (errno == EAGAIN) 492 Py_RETURN_NONE; 493 PyErr_SetFromErrno(PyExc_IOError); 494 return NULL; 495 } 496 497 return PyLong_FromSsize_t(n); 498 } 499 500 static size_t 501 new_buffersize(fileio *self, size_t currentsize) 502 { 503 #ifdef HAVE_FSTAT 504 off_t pos, end; 505 struct stat st; 506 if (fstat(self->fd, &st) == 0) { 507 end = st.st_size; 508 pos = lseek(self->fd, 0L, SEEK_CUR); 509 /* Files claiming a size smaller than SMALLCHUNK may 510 actually be streaming pseudo-files. In this case, we 511 apply the more aggressive algorithm below. 512 */ 513 if (end >= SMALLCHUNK && end >= pos && pos >= 0) { 514 /* Add 1 so if the file were to grow we'd notice. */ 515 return currentsize + end - pos + 1; 516 } 517 } 518 #endif 519 /* Expand the buffer by an amount proportional to the current size, 520 giving us amortized linear-time behavior. Use a less-than-double 521 growth factor to avoid excessive allocation. */ 522 return currentsize + (currentsize >> 3) + 6; 523 } 524 525 static PyObject * 526 fileio_readall(fileio *self) 527 { 528 PyObject *result; 529 Py_ssize_t total = 0; 530 Py_ssize_t n; 531 532 if (self->fd < 0) 533 return err_closed(); 534 if (!_PyVerify_fd(self->fd)) 535 return PyErr_SetFromErrno(PyExc_IOError); 536 537 result = PyBytes_FromStringAndSize(NULL, SMALLCHUNK); 538 if (result == NULL) 539 return NULL; 540 541 while (1) { 542 size_t newsize = new_buffersize(self, total); 543 if (newsize > PY_SSIZE_T_MAX || newsize <= 0) { 544 PyErr_SetString(PyExc_OverflowError, 545 "unbounded read returned more bytes " 546 "than a Python string can hold "); 547 Py_DECREF(result); 548 return NULL; 549 } 550 551 if (PyBytes_GET_SIZE(result) < (Py_ssize_t)newsize) { 552 if (_PyBytes_Resize(&result, newsize) < 0) 553 return NULL; /* result has been freed */ 554 } 555 Py_BEGIN_ALLOW_THREADS 556 errno = 0; 557 n = newsize - total; 558 #if defined(MS_WIN64) || defined(MS_WINDOWS) 559 if (n > INT_MAX) 560 n = INT_MAX; 561 n = read(self->fd, 562 PyBytes_AS_STRING(result) + total, 563 (int)n); 564 #else 565 n = read(self->fd, 566 PyBytes_AS_STRING(result) + total, 567 n); 568 #endif 569 Py_END_ALLOW_THREADS 570 if (n == 0) 571 break; 572 if (n < 0) { 573 if (errno == EINTR) { 574 if (PyErr_CheckSignals()) { 575 Py_DECREF(result); 576 return NULL; 577 } 578 continue; 579 } 580 if (errno == EAGAIN) { 581 if (total > 0) 582 break; 583 Py_DECREF(result); 584 Py_RETURN_NONE; 585 } 586 Py_DECREF(result); 587 PyErr_SetFromErrno(PyExc_IOError); 588 return NULL; 589 } 590 total += n; 591 } 592 593 if (PyBytes_GET_SIZE(result) > total) { 594 if (_PyBytes_Resize(&result, total) < 0) { 595 /* This should never happen, but just in case */ 596 return NULL; 597 } 598 } 599 return result; 600 } 601 602 static PyObject * 603 fileio_read(fileio *self, PyObject *args) 604 { 605 char *ptr; 606 Py_ssize_t n; 607 Py_ssize_t size = -1; 608 PyObject *bytes; 609 610 if (self->fd < 0) 611 return err_closed(); 612 if (!self->readable) 613 return err_mode("reading"); 614 615 if (!PyArg_ParseTuple(args, "|O&", &_PyIO_ConvertSsize_t, &size)) 616 return NULL; 617 618 if (size < 0) { 619 return fileio_readall(self); 620 } 621 622 #if defined(MS_WIN64) || defined(MS_WINDOWS) 623 if (size > INT_MAX) 624 size = INT_MAX; 625 #endif 626 bytes = PyBytes_FromStringAndSize(NULL, size); 627 if (bytes == NULL) 628 return NULL; 629 ptr = PyBytes_AS_STRING(bytes); 630 631 if (_PyVerify_fd(self->fd)) { 632 Py_BEGIN_ALLOW_THREADS 633 errno = 0; 634 #if defined(MS_WIN64) || defined(MS_WINDOWS) 635 n = read(self->fd, ptr, (int)size); 636 #else 637 n = read(self->fd, ptr, size); 638 #endif 639 Py_END_ALLOW_THREADS 640 } else 641 n = -1; 642 643 if (n < 0) { 644 Py_DECREF(bytes); 645 if (errno == EAGAIN) 646 Py_RETURN_NONE; 647 PyErr_SetFromErrno(PyExc_IOError); 648 return NULL; 649 } 650 651 if (n != size) { 652 if (_PyBytes_Resize(&bytes, n) < 0) 653 return NULL; 654 } 655 656 return (PyObject *) bytes; 657 } 658 659 static PyObject * 660 fileio_write(fileio *self, PyObject *args) 661 { 662 Py_buffer pbuf; 663 Py_ssize_t n, len; 664 665 if (self->fd < 0) 666 return err_closed(); 667 if (!self->writable) 668 return err_mode("writing"); 669 670 if (!PyArg_ParseTuple(args, "s*", &pbuf)) 671 return NULL; 672 673 if (_PyVerify_fd(self->fd)) { 674 Py_BEGIN_ALLOW_THREADS 675 errno = 0; 676 len = pbuf.len; 677 #if defined(MS_WIN64) || defined(MS_WINDOWS) 678 if (len > INT_MAX) 679 len = INT_MAX; 680 n = write(self->fd, pbuf.buf, (int)len); 681 #else 682 n = write(self->fd, pbuf.buf, len); 683 #endif 684 Py_END_ALLOW_THREADS 685 } else 686 n = -1; 687 688 PyBuffer_Release(&pbuf); 689 690 if (n < 0) { 691 if (errno == EAGAIN) 692 Py_RETURN_NONE; 693 PyErr_SetFromErrno(PyExc_IOError); 694 return NULL; 695 } 696 697 return PyLong_FromSsize_t(n); 698 } 699 700 /* XXX Windows support below is likely incomplete */ 701 702 /* Cribbed from posix_lseek() */ 703 static PyObject * 704 portable_lseek(int fd, PyObject *posobj, int whence) 705 { 706 Py_off_t pos, res; 707 708 #ifdef SEEK_SET 709 /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */ 710 switch (whence) { 711 #if SEEK_SET != 0 712 case 0: whence = SEEK_SET; break; 713 #endif 714 #if SEEK_CUR != 1 715 case 1: whence = SEEK_CUR; break; 716 #endif 717 #if SEEK_END != 2 718 case 2: whence = SEEK_END; break; 719 #endif 720 } 721 #endif /* SEEK_SET */ 722 723 if (posobj == NULL) 724 pos = 0; 725 else { 726 if(PyFloat_Check(posobj)) { 727 PyErr_SetString(PyExc_TypeError, "an integer is required"); 728 return NULL; 729 } 730 #if defined(HAVE_LARGEFILE_SUPPORT) 731 pos = PyLong_AsLongLong(posobj); 732 #else 733 pos = PyLong_AsLong(posobj); 734 #endif 735 if (PyErr_Occurred()) 736 return NULL; 737 } 738 739 if (_PyVerify_fd(fd)) { 740 Py_BEGIN_ALLOW_THREADS 741 #if defined(MS_WIN64) || defined(MS_WINDOWS) 742 res = _lseeki64(fd, pos, whence); 743 #else 744 res = lseek(fd, pos, whence); 745 #endif 746 Py_END_ALLOW_THREADS 747 } else 748 res = -1; 749 if (res < 0) 750 return PyErr_SetFromErrno(PyExc_IOError); 751 752 #if defined(HAVE_LARGEFILE_SUPPORT) 753 return PyLong_FromLongLong(res); 754 #else 755 return PyLong_FromLong(res); 756 #endif 757 } 758 759 static PyObject * 760 fileio_seek(fileio *self, PyObject *args) 761 { 762 PyObject *posobj; 763 int whence = 0; 764 765 if (self->fd < 0) 766 return err_closed(); 767 768 if (!PyArg_ParseTuple(args, "O|i", &posobj, &whence)) 769 return NULL; 770 771 return portable_lseek(self->fd, posobj, whence); 772 } 773 774 static PyObject * 775 fileio_tell(fileio *self, PyObject *args) 776 { 777 if (self->fd < 0) 778 return err_closed(); 779 780 return portable_lseek(self->fd, NULL, 1); 781 } 782 783 #ifdef HAVE_FTRUNCATE 784 static PyObject * 785 fileio_truncate(fileio *self, PyObject *args) 786 { 787 PyObject *posobj = NULL; /* the new size wanted by the user */ 788 #ifndef MS_WINDOWS 789 Py_off_t pos; 790 #endif 791 int ret; 792 int fd; 793 794 fd = self->fd; 795 if (fd < 0) 796 return err_closed(); 797 if (!self->writable) 798 return err_mode("writing"); 799 800 if (!PyArg_ParseTuple(args, "|O", &posobj)) 801 return NULL; 802 803 if (posobj == Py_None || posobj == NULL) { 804 /* Get the current position. */ 805 posobj = portable_lseek(fd, NULL, 1); 806 if (posobj == NULL) 807 return NULL; 808 } 809 else { 810 Py_INCREF(posobj); 811 } 812 813 #ifdef MS_WINDOWS 814 /* MS _chsize doesn't work if newsize doesn't fit in 32 bits, 815 so don't even try using it. */ 816 { 817 PyObject *oldposobj, *tempposobj; 818 HANDLE hFile; 819 820 /* we save the file pointer position */ 821 oldposobj = portable_lseek(fd, NULL, 1); 822 if (oldposobj == NULL) { 823 Py_DECREF(posobj); 824 return NULL; 825 } 826 827 /* we then move to the truncation position */ 828 tempposobj = portable_lseek(fd, posobj, 0); 829 if (tempposobj == NULL) { 830 Py_DECREF(oldposobj); 831 Py_DECREF(posobj); 832 return NULL; 833 } 834 Py_DECREF(tempposobj); 835 836 /* Truncate. Note that this may grow the file! */ 837 Py_BEGIN_ALLOW_THREADS 838 errno = 0; 839 hFile = (HANDLE)_get_osfhandle(fd); 840 ret = hFile == (HANDLE)-1; /* testing for INVALID_HANDLE value */ 841 if (ret == 0) { 842 ret = SetEndOfFile(hFile) == 0; 843 if (ret) 844 errno = EACCES; 845 } 846 Py_END_ALLOW_THREADS 847 848 /* we restore the file pointer position in any case */ 849 tempposobj = portable_lseek(fd, oldposobj, 0); 850 Py_DECREF(oldposobj); 851 if (tempposobj == NULL) { 852 Py_DECREF(posobj); 853 return NULL; 854 } 855 Py_DECREF(tempposobj); 856 } 857 #else 858 859 #if defined(HAVE_LARGEFILE_SUPPORT) 860 pos = PyLong_AsLongLong(posobj); 861 #else 862 pos = PyLong_AsLong(posobj); 863 #endif 864 if (PyErr_Occurred()){ 865 Py_DECREF(posobj); 866 return NULL; 867 } 868 869 Py_BEGIN_ALLOW_THREADS 870 errno = 0; 871 ret = ftruncate(fd, pos); 872 Py_END_ALLOW_THREADS 873 874 #endif /* !MS_WINDOWS */ 875 876 if (ret != 0) { 877 Py_DECREF(posobj); 878 PyErr_SetFromErrno(PyExc_IOError); 879 return NULL; 880 } 881 882 return posobj; 883 } 884 #endif /* HAVE_FTRUNCATE */ 885 886 static char * 887 mode_string(fileio *self) 888 { 889 if (self->appending) { 890 if (self->readable) 891 return "ab+"; 892 else 893 return "ab"; 894 } 895 else if (self->readable) { 896 if (self->writable) 897 return "rb+"; 898 else 899 return "rb"; 900 } 901 else 902 return "wb"; 903 } 904 905 static PyObject * 906 fileio_repr(fileio *self) 907 { 908 PyObject *nameobj, *res; 909 910 if (self->fd < 0) 911 return PyString_FromFormat("<_io.FileIO [closed]>"); 912 913 nameobj = PyObject_GetAttrString((PyObject *) self, "name"); 914 if (nameobj == NULL) { 915 if (PyErr_ExceptionMatches(PyExc_AttributeError)) 916 PyErr_Clear(); 917 else 918 return NULL; 919 res = PyString_FromFormat("<_io.FileIO fd=%d mode='%s'>", 920 self->fd, mode_string(self)); 921 } 922 else { 923 PyObject *repr = PyObject_Repr(nameobj); 924 Py_DECREF(nameobj); 925 if (repr == NULL) 926 return NULL; 927 res = PyString_FromFormat("<_io.FileIO name=%s mode='%s'>", 928 PyString_AS_STRING(repr), 929 mode_string(self)); 930 Py_DECREF(repr); 931 } 932 return res; 933 } 934 935 static PyObject * 936 fileio_isatty(fileio *self) 937 { 938 long res; 939 940 if (self->fd < 0) 941 return err_closed(); 942 Py_BEGIN_ALLOW_THREADS 943 res = isatty(self->fd); 944 Py_END_ALLOW_THREADS 945 return PyBool_FromLong(res); 946 } 947 948 949 PyDoc_STRVAR(fileio_doc, 950 "file(name: str[, mode: str]) -> file IO object\n" 951 "\n" 952 "Open a file. The mode can be 'r' (default), 'w' or 'a' for reading,\n" 953 "writing or appending. The file will be created if it doesn't exist\n" 954 "when opened for writing or appending; it will be truncated when\n" 955 "opened for writing. Add a '+' to the mode to allow simultaneous\n" 956 "reading and writing."); 957 958 PyDoc_STRVAR(read_doc, 959 "read(size: int) -> bytes. read at most size bytes, returned as bytes.\n" 960 "\n" 961 "Only makes one system call, so less data may be returned than requested\n" 962 "In non-blocking mode, returns None if no data is available.\n" 963 "On end-of-file, returns ''."); 964 965 PyDoc_STRVAR(readall_doc, 966 "readall() -> bytes. read all data from the file, returned as bytes.\n" 967 "\n" 968 "In non-blocking mode, returns as much as is immediately available,\n" 969 "or None if no data is available. On end-of-file, returns ''."); 970 971 PyDoc_STRVAR(write_doc, 972 "write(b: bytes) -> int. Write bytes b to file, return number written.\n" 973 "\n" 974 "Only makes one system call, so not all of the data may be written.\n" 975 "The number of bytes actually written is returned. In non-blocking mode,\n" 976 "returns None if the write would block." 977 ); 978 979 PyDoc_STRVAR(fileno_doc, 980 "fileno() -> int. Return the underlying file descriptor (an integer)."); 981 982 PyDoc_STRVAR(seek_doc, 983 "seek(offset: int[, whence: int]) -> int. Move to new file position\n" 984 "and return the file position.\n" 985 "\n" 986 "Argument offset is a byte count. Optional argument whence defaults to\n" 987 "SEEK_SET or 0 (offset from start of file, offset should be >= 0); other values\n" 988 "are SEEK_CUR or 1 (move relative to current position, positive or negative),\n" 989 "and SEEK_END or 2 (move relative to end of file, usually negative, although\n" 990 "many platforms allow seeking beyond the end of a file).\n" 991 "\n" 992 "Note that not all file objects are seekable."); 993 994 #ifdef HAVE_FTRUNCATE 995 PyDoc_STRVAR(truncate_doc, 996 "truncate([size: int]) -> int. Truncate the file to at most size bytes and\n" 997 "return the truncated size.\n" 998 "\n" 999 "Size defaults to the current file position, as returned by tell().\n" 1000 "The current file position is changed to the value of size."); 1001 #endif 1002 1003 PyDoc_STRVAR(tell_doc, 1004 "tell() -> int. Current file position.\n" 1005 "\n" 1006 "Can raise OSError for non seekable files." 1007 ); 1008 1009 PyDoc_STRVAR(readinto_doc, 1010 "readinto() -> Same as RawIOBase.readinto()."); 1011 1012 PyDoc_STRVAR(close_doc, 1013 "close() -> None. Close the file.\n" 1014 "\n" 1015 "A closed file cannot be used for further I/O operations. close() may be\n" 1016 "called more than once without error."); 1017 1018 PyDoc_STRVAR(isatty_doc, 1019 "isatty() -> bool. True if the file is connected to a TTY device."); 1020 1021 PyDoc_STRVAR(seekable_doc, 1022 "seekable() -> bool. True if file supports random-access."); 1023 1024 PyDoc_STRVAR(readable_doc, 1025 "readable() -> bool. True if file was opened in a read mode."); 1026 1027 PyDoc_STRVAR(writable_doc, 1028 "writable() -> bool. True if file was opened in a write mode."); 1029 1030 static PyMethodDef fileio_methods[] = { 1031 {"read", (PyCFunction)fileio_read, METH_VARARGS, read_doc}, 1032 {"readall", (PyCFunction)fileio_readall, METH_NOARGS, readall_doc}, 1033 {"readinto", (PyCFunction)fileio_readinto, METH_VARARGS, readinto_doc}, 1034 {"write", (PyCFunction)fileio_write, METH_VARARGS, write_doc}, 1035 {"seek", (PyCFunction)fileio_seek, METH_VARARGS, seek_doc}, 1036 {"tell", (PyCFunction)fileio_tell, METH_VARARGS, tell_doc}, 1037 #ifdef HAVE_FTRUNCATE 1038 {"truncate", (PyCFunction)fileio_truncate, METH_VARARGS, truncate_doc}, 1039 #endif 1040 {"close", (PyCFunction)fileio_close, METH_NOARGS, close_doc}, 1041 {"seekable", (PyCFunction)fileio_seekable, METH_NOARGS, seekable_doc}, 1042 {"readable", (PyCFunction)fileio_readable, METH_NOARGS, readable_doc}, 1043 {"writable", (PyCFunction)fileio_writable, METH_NOARGS, writable_doc}, 1044 {"fileno", (PyCFunction)fileio_fileno, METH_NOARGS, fileno_doc}, 1045 {"isatty", (PyCFunction)fileio_isatty, METH_NOARGS, isatty_doc}, 1046 {NULL, NULL} /* sentinel */ 1047 }; 1048 1049 /* 'closed' and 'mode' are attributes for backwards compatibility reasons. */ 1050 1051 static PyObject * 1052 get_closed(fileio *self, void *closure) 1053 { 1054 return PyBool_FromLong((long)(self->fd < 0)); 1055 } 1056 1057 static PyObject * 1058 get_closefd(fileio *self, void *closure) 1059 { 1060 return PyBool_FromLong((long)(self->closefd)); 1061 } 1062 1063 static PyObject * 1064 get_mode(fileio *self, void *closure) 1065 { 1066 return PyUnicode_FromString(mode_string(self)); 1067 } 1068 1069 static PyGetSetDef fileio_getsetlist[] = { 1070 {"closed", (getter)get_closed, NULL, "True if the file is closed"}, 1071 {"closefd", (getter)get_closefd, NULL, 1072 "True if the file descriptor will be closed by close()."}, 1073 {"mode", (getter)get_mode, NULL, "String giving the file mode"}, 1074 {NULL}, 1075 }; 1076 1077 PyTypeObject PyFileIO_Type = { 1078 PyVarObject_HEAD_INIT(NULL, 0) 1079 "_io.FileIO", 1080 sizeof(fileio), 1081 0, 1082 (destructor)fileio_dealloc, /* tp_dealloc */ 1083 0, /* tp_print */ 1084 0, /* tp_getattr */ 1085 0, /* tp_setattr */ 1086 0, /* tp_reserved */ 1087 (reprfunc)fileio_repr, /* tp_repr */ 1088 0, /* tp_as_number */ 1089 0, /* tp_as_sequence */ 1090 0, /* tp_as_mapping */ 1091 0, /* tp_hash */ 1092 0, /* tp_call */ 1093 0, /* tp_str */ 1094 PyObject_GenericGetAttr, /* tp_getattro */ 1095 0, /* tp_setattro */ 1096 0, /* tp_as_buffer */ 1097 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE 1098 | Py_TPFLAGS_HAVE_GC, /* tp_flags */ 1099 fileio_doc, /* tp_doc */ 1100 (traverseproc)fileio_traverse, /* tp_traverse */ 1101 (inquiry)fileio_clear, /* tp_clear */ 1102 0, /* tp_richcompare */ 1103 offsetof(fileio, weakreflist), /* tp_weaklistoffset */ 1104 0, /* tp_iter */ 1105 0, /* tp_iternext */ 1106 fileio_methods, /* tp_methods */ 1107 0, /* tp_members */ 1108 fileio_getsetlist, /* tp_getset */ 1109 0, /* tp_base */ 1110 0, /* tp_dict */ 1111 0, /* tp_descr_get */ 1112 0, /* tp_descr_set */ 1113 offsetof(fileio, dict), /* tp_dictoffset */ 1114 fileio_init, /* tp_init */ 1115 PyType_GenericAlloc, /* tp_alloc */ 1116 fileio_new, /* tp_new */ 1117 PyObject_GC_Del, /* tp_free */ 1118 }; 1119