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