Python-2.7.3/Modules/_io/fileio.c

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