]> git.proxmox.com Git - mirror_edk2.git/blob - AppPkg/Applications/Python/Python-2.7.10/Modules/_io/fileio.c
b69d36602b094a5742a6616cbbdef5bb4e202778
[mirror_edk2.git] / AppPkg / Applications / Python / Python-2.7.10 / Modules / _io / fileio.c
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 };