source: python/trunk/Modules/_io/fileio.c

Last change on this file was 391, checked in by dmik, 11 years ago

python: Merge vendor 2.7.6 to trunk.

  • Property svn:eol-style set to native
File size: 29.0 KB
Line 
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
45typedef 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
57PyTypeObject PyFileIO_Type;
58
59#define PyFileIO_Check(op) (PyObject_TypeCheck((op), &PyFileIO_Type))
60
61int
62_PyFileIO_closed(PyObject *self)
63{
64 return ((fileio *)self)->fd < 0;
65}
66
67static PyObject *
68portable_lseek(int fd, PyObject *posobj, int whence);
69
70static PyObject *portable_lseek(int fd, PyObject *posobj, int whence);
71
72/* Returns 0 on success, -1 with exception set on failure. */
73static int
74internal_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
101static PyObject *
102fileio_close(fileio *self)
103{
104 if (!self->closefd) {
105 self->fd = -1;
106 Py_RETURN_NONE;
107 }
108 errno = internal_close(self);
109 if (errno < 0)
110 return NULL;
111
112 return PyObject_CallMethod((PyObject*)&PyRawIOBase_Type,
113 "close", "O", self);
114}
115
116static PyObject *
117fileio_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
141static int
142dircheck(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
157static int
158check_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
176static int
177fileio_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 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 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
379static int
380fileio_traverse(fileio *self, visitproc visit, void *arg)
381{
382 Py_VISIT(self->dict);
383 return 0;
384}
385
386static int
387fileio_clear(fileio *self)
388{
389 Py_CLEAR(self->dict);
390 return 0;
391}
392
393static void
394fileio_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
405static PyObject *
406err_closed(void)
407{
408 PyErr_SetString(PyExc_ValueError, "I/O operation on closed file");
409 return NULL;
410}
411
412static PyObject *
413err_mode(char *action)
414{
415 PyErr_Format(PyExc_ValueError, "File not open for %s", action);
416 return NULL;
417}
418
419static PyObject *
420fileio_fileno(fileio *self)
421{
422 if (self->fd < 0)
423 return err_closed();
424 return PyInt_FromLong((long) self->fd);
425}
426
427static PyObject *
428fileio_readable(fileio *self)
429{
430 if (self->fd < 0)
431 return err_closed();
432 return PyBool_FromLong((long) self->readable);
433}
434
435static PyObject *
436fileio_writable(fileio *self)
437{
438 if (self->fd < 0)
439 return err_closed();
440 return PyBool_FromLong((long) self->writable);
441}
442
443static PyObject *
444fileio_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
461static PyObject *
462fileio_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
500static size_t
501new_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
525static PyObject *
526fileio_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 if (total == 0) {
554 Py_DECREF(result);
555 return NULL;
556 }
557 PyErr_Clear();
558 break;
559 }
560 }
561 Py_BEGIN_ALLOW_THREADS
562 errno = 0;
563 n = newsize - total;
564#if defined(MS_WIN64) || defined(MS_WINDOWS)
565 if (n > INT_MAX)
566 n = INT_MAX;
567 n = read(self->fd,
568 PyBytes_AS_STRING(result) + total,
569 (int)n);
570#else
571 n = read(self->fd,
572 PyBytes_AS_STRING(result) + total,
573 n);
574#endif
575 Py_END_ALLOW_THREADS
576 if (n == 0)
577 break;
578 if (n < 0) {
579 if (errno == EINTR) {
580 if (PyErr_CheckSignals()) {
581 Py_DECREF(result);
582 return NULL;
583 }
584 continue;
585 }
586 if (total > 0)
587 break;
588 if (errno == EAGAIN) {
589 Py_DECREF(result);
590 Py_RETURN_NONE;
591 }
592 Py_DECREF(result);
593 PyErr_SetFromErrno(PyExc_IOError);
594 return NULL;
595 }
596 total += n;
597 }
598
599 if (PyBytes_GET_SIZE(result) > total) {
600 if (_PyBytes_Resize(&result, total) < 0) {
601 /* This should never happen, but just in case */
602 Py_DECREF(result);
603 return NULL;
604 }
605 }
606 return result;
607}
608
609static PyObject *
610fileio_read(fileio *self, PyObject *args)
611{
612 char *ptr;
613 Py_ssize_t n;
614 Py_ssize_t size = -1;
615 PyObject *bytes;
616
617 if (self->fd < 0)
618 return err_closed();
619 if (!self->readable)
620 return err_mode("reading");
621
622 if (!PyArg_ParseTuple(args, "|O&", &_PyIO_ConvertSsize_t, &size))
623 return NULL;
624
625 if (size < 0) {
626 return fileio_readall(self);
627 }
628
629#if defined(MS_WIN64) || defined(MS_WINDOWS)
630 if (size > INT_MAX)
631 size = INT_MAX;
632#endif
633 bytes = PyBytes_FromStringAndSize(NULL, size);
634 if (bytes == NULL)
635 return NULL;
636 ptr = PyBytes_AS_STRING(bytes);
637
638 if (_PyVerify_fd(self->fd)) {
639 Py_BEGIN_ALLOW_THREADS
640 errno = 0;
641#if defined(MS_WIN64) || defined(MS_WINDOWS)
642 n = read(self->fd, ptr, (int)size);
643#else
644 n = read(self->fd, ptr, size);
645#endif
646 Py_END_ALLOW_THREADS
647 } else
648 n = -1;
649
650 if (n < 0) {
651 Py_DECREF(bytes);
652 if (errno == EAGAIN)
653 Py_RETURN_NONE;
654 PyErr_SetFromErrno(PyExc_IOError);
655 return NULL;
656 }
657
658 if (n != size) {
659 if (_PyBytes_Resize(&bytes, n) < 0) {
660 Py_DECREF(bytes);
661 return NULL;
662 }
663 }
664
665 return (PyObject *) bytes;
666}
667
668static PyObject *
669fileio_write(fileio *self, PyObject *args)
670{
671 Py_buffer pbuf;
672 Py_ssize_t n, len;
673
674 if (self->fd < 0)
675 return err_closed();
676 if (!self->writable)
677 return err_mode("writing");
678
679 if (!PyArg_ParseTuple(args, "s*", &pbuf))
680 return NULL;
681
682 if (_PyVerify_fd(self->fd)) {
683 Py_BEGIN_ALLOW_THREADS
684 errno = 0;
685 len = pbuf.len;
686#if defined(MS_WIN64) || defined(MS_WINDOWS)
687 if (len > INT_MAX)
688 len = INT_MAX;
689 n = write(self->fd, pbuf.buf, (int)len);
690#else
691 n = write(self->fd, pbuf.buf, len);
692#endif
693 Py_END_ALLOW_THREADS
694 } else
695 n = -1;
696
697 PyBuffer_Release(&pbuf);
698
699 if (n < 0) {
700 if (errno == EAGAIN)
701 Py_RETURN_NONE;
702 PyErr_SetFromErrno(PyExc_IOError);
703 return NULL;
704 }
705
706 return PyLong_FromSsize_t(n);
707}
708
709/* XXX Windows support below is likely incomplete */
710
711/* Cribbed from posix_lseek() */
712static PyObject *
713portable_lseek(int fd, PyObject *posobj, int whence)
714{
715 Py_off_t pos, res;
716
717#ifdef SEEK_SET
718 /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
719 switch (whence) {
720#if SEEK_SET != 0
721 case 0: whence = SEEK_SET; break;
722#endif
723#if SEEK_CUR != 1
724 case 1: whence = SEEK_CUR; break;
725#endif
726#if SEEK_END != 2
727 case 2: whence = SEEK_END; break;
728#endif
729 }
730#endif /* SEEK_SET */
731
732 if (posobj == NULL)
733 pos = 0;
734 else {
735 if(PyFloat_Check(posobj)) {
736 PyErr_SetString(PyExc_TypeError, "an integer is required");
737 return NULL;
738 }
739#if defined(HAVE_LARGEFILE_SUPPORT)
740 pos = PyLong_AsLongLong(posobj);
741#else
742 pos = PyLong_AsLong(posobj);
743#endif
744 if (PyErr_Occurred())
745 return NULL;
746 }
747
748 if (_PyVerify_fd(fd)) {
749 Py_BEGIN_ALLOW_THREADS
750#if defined(MS_WIN64) || defined(MS_WINDOWS)
751 res = _lseeki64(fd, pos, whence);
752#else
753 res = lseek(fd, pos, whence);
754#endif
755 Py_END_ALLOW_THREADS
756 } else
757 res = -1;
758 if (res < 0)
759 return PyErr_SetFromErrno(PyExc_IOError);
760
761#if defined(HAVE_LARGEFILE_SUPPORT)
762 return PyLong_FromLongLong(res);
763#else
764 return PyLong_FromLong(res);
765#endif
766}
767
768static PyObject *
769fileio_seek(fileio *self, PyObject *args)
770{
771 PyObject *posobj;
772 int whence = 0;
773
774 if (self->fd < 0)
775 return err_closed();
776
777 if (!PyArg_ParseTuple(args, "O|i", &posobj, &whence))
778 return NULL;
779
780 return portable_lseek(self->fd, posobj, whence);
781}
782
783static PyObject *
784fileio_tell(fileio *self, PyObject *args)
785{
786 if (self->fd < 0)
787 return err_closed();
788
789 return portable_lseek(self->fd, NULL, 1);
790}
791
792#ifdef HAVE_FTRUNCATE
793static PyObject *
794fileio_truncate(fileio *self, PyObject *args)
795{
796 PyObject *posobj = NULL; /* the new size wanted by the user */
797#ifndef MS_WINDOWS
798 Py_off_t pos;
799#endif
800 int ret;
801 int fd;
802
803 fd = self->fd;
804 if (fd < 0)
805 return err_closed();
806 if (!self->writable)
807 return err_mode("writing");
808
809 if (!PyArg_ParseTuple(args, "|O", &posobj))
810 return NULL;
811
812 if (posobj == Py_None || posobj == NULL) {
813 /* Get the current position. */
814 posobj = portable_lseek(fd, NULL, 1);
815 if (posobj == NULL)
816 return NULL;
817 }
818 else {
819 Py_INCREF(posobj);
820 }
821
822#ifdef MS_WINDOWS
823 /* MS _chsize doesn't work if newsize doesn't fit in 32 bits,
824 so don't even try using it. */
825 {
826 PyObject *oldposobj, *tempposobj;
827 HANDLE hFile;
828
829 /* we save the file pointer position */
830 oldposobj = portable_lseek(fd, NULL, 1);
831 if (oldposobj == NULL) {
832 Py_DECREF(posobj);
833 return NULL;
834 }
835
836 /* we then move to the truncation position */
837 tempposobj = portable_lseek(fd, posobj, 0);
838 if (tempposobj == NULL) {
839 Py_DECREF(oldposobj);
840 Py_DECREF(posobj);
841 return NULL;
842 }
843 Py_DECREF(tempposobj);
844
845 /* Truncate. Note that this may grow the file! */
846 Py_BEGIN_ALLOW_THREADS
847 errno = 0;
848 hFile = (HANDLE)_get_osfhandle(fd);
849 ret = hFile == (HANDLE)-1; /* testing for INVALID_HANDLE value */
850 if (ret == 0) {
851 ret = SetEndOfFile(hFile) == 0;
852 if (ret)
853 errno = EACCES;
854 }
855 Py_END_ALLOW_THREADS
856
857 /* we restore the file pointer position in any case */
858 tempposobj = portable_lseek(fd, oldposobj, 0);
859 Py_DECREF(oldposobj);
860 if (tempposobj == NULL) {
861 Py_DECREF(posobj);
862 return NULL;
863 }
864 Py_DECREF(tempposobj);
865 }
866#else
867
868#if defined(HAVE_LARGEFILE_SUPPORT)
869 pos = PyLong_AsLongLong(posobj);
870#else
871 pos = PyLong_AsLong(posobj);
872#endif
873 if (PyErr_Occurred()){
874 Py_DECREF(posobj);
875 return NULL;
876 }
877
878 Py_BEGIN_ALLOW_THREADS
879 errno = 0;
880 ret = ftruncate(fd, pos);
881 Py_END_ALLOW_THREADS
882
883#endif /* !MS_WINDOWS */
884
885 if (ret != 0) {
886 Py_DECREF(posobj);
887 PyErr_SetFromErrno(PyExc_IOError);
888 return NULL;
889 }
890
891 return posobj;
892}
893#endif /* HAVE_FTRUNCATE */
894
895static char *
896mode_string(fileio *self)
897{
898 if (self->appending) {
899 if (self->readable)
900 return "ab+";
901 else
902 return "ab";
903 }
904 else if (self->readable) {
905 if (self->writable)
906 return "rb+";
907 else
908 return "rb";
909 }
910 else
911 return "wb";
912}
913
914static PyObject *
915fileio_repr(fileio *self)
916{
917 PyObject *nameobj, *res;
918
919 if (self->fd < 0)
920 return PyString_FromFormat("<_io.FileIO [closed]>");
921
922 nameobj = PyObject_GetAttrString((PyObject *) self, "name");
923 if (nameobj == NULL) {
924 if (PyErr_ExceptionMatches(PyExc_AttributeError))
925 PyErr_Clear();
926 else
927 return NULL;
928 res = PyString_FromFormat("<_io.FileIO fd=%d mode='%s'>",
929 self->fd, mode_string(self));
930 }
931 else {
932 PyObject *repr = PyObject_Repr(nameobj);
933 Py_DECREF(nameobj);
934 if (repr == NULL)
935 return NULL;
936 res = PyString_FromFormat("<_io.FileIO name=%s mode='%s'>",
937 PyString_AS_STRING(repr),
938 mode_string(self));
939 Py_DECREF(repr);
940 }
941 return res;
942}
943
944static PyObject *
945fileio_isatty(fileio *self)
946{
947 long res;
948
949 if (self->fd < 0)
950 return err_closed();
951 Py_BEGIN_ALLOW_THREADS
952 res = isatty(self->fd);
953 Py_END_ALLOW_THREADS
954 return PyBool_FromLong(res);
955}
956
957
958PyDoc_STRVAR(fileio_doc,
959"file(name: str[, mode: str]) -> file IO object\n"
960"\n"
961"Open a file. The mode can be 'r', 'w' or 'a' for reading (default),\n"
962"writing or appending. The file will be created if it doesn't exist\n"
963"when opened for writing or appending; it will be truncated when\n"
964"opened for writing. Add a '+' to the mode to allow simultaneous\n"
965"reading and writing.");
966
967PyDoc_STRVAR(read_doc,
968"read(size: int) -> bytes. read at most size bytes, returned as bytes.\n"
969"\n"
970"Only makes one system call, so less data may be returned than requested\n"
971"In non-blocking mode, returns None if no data is available.\n"
972"On end-of-file, returns ''.");
973
974PyDoc_STRVAR(readall_doc,
975"readall() -> bytes. read all data from the file, returned as bytes.\n"
976"\n"
977"In non-blocking mode, returns as much as is immediately available,\n"
978"or None if no data is available. On end-of-file, returns ''.");
979
980PyDoc_STRVAR(write_doc,
981"write(b: bytes) -> int. Write bytes b to file, return number written.\n"
982"\n"
983"Only makes one system call, so not all of the data may be written.\n"
984"The number of bytes actually written is returned.");
985
986PyDoc_STRVAR(fileno_doc,
987"fileno() -> int. \"file descriptor\".\n"
988"\n"
989"This is needed for lower-level file interfaces, such the fcntl module.");
990
991PyDoc_STRVAR(seek_doc,
992"seek(offset: int[, whence: int]) -> None. Move to new file position.\n"
993"\n"
994"Argument offset is a byte count. Optional argument whence defaults to\n"
995"0 (offset from start of file, offset should be >= 0); other values are 1\n"
996"(move relative to current position, positive or negative), and 2 (move\n"
997"relative to end of file, usually negative, although many platforms allow\n"
998"seeking beyond the end of a file)."
999"\n"
1000"Note that not all file objects are seekable.");
1001
1002#ifdef HAVE_FTRUNCATE
1003PyDoc_STRVAR(truncate_doc,
1004"truncate([size: int]) -> None. Truncate the file to at most size bytes.\n"
1005"\n"
1006"Size defaults to the current file position, as returned by tell()."
1007"The current file position is changed to the value of size.");
1008#endif
1009
1010PyDoc_STRVAR(tell_doc,
1011"tell() -> int. Current file position");
1012
1013PyDoc_STRVAR(readinto_doc,
1014"readinto() -> Same as RawIOBase.readinto().");
1015
1016PyDoc_STRVAR(close_doc,
1017"close() -> None. Close the file.\n"
1018"\n"
1019"A closed file cannot be used for further I/O operations. close() may be\n"
1020"called more than once without error. Changes the fileno to -1.");
1021
1022PyDoc_STRVAR(isatty_doc,
1023"isatty() -> bool. True if the file is connected to a tty device.");
1024
1025PyDoc_STRVAR(seekable_doc,
1026"seekable() -> bool. True if file supports random-access.");
1027
1028PyDoc_STRVAR(readable_doc,
1029"readable() -> bool. True if file was opened in a read mode.");
1030
1031PyDoc_STRVAR(writable_doc,
1032"writable() -> bool. True if file was opened in a write mode.");
1033
1034static PyMethodDef fileio_methods[] = {
1035 {"read", (PyCFunction)fileio_read, METH_VARARGS, read_doc},
1036 {"readall", (PyCFunction)fileio_readall, METH_NOARGS, readall_doc},
1037 {"readinto", (PyCFunction)fileio_readinto, METH_VARARGS, readinto_doc},
1038 {"write", (PyCFunction)fileio_write, METH_VARARGS, write_doc},
1039 {"seek", (PyCFunction)fileio_seek, METH_VARARGS, seek_doc},
1040 {"tell", (PyCFunction)fileio_tell, METH_VARARGS, tell_doc},
1041#ifdef HAVE_FTRUNCATE
1042 {"truncate", (PyCFunction)fileio_truncate, METH_VARARGS, truncate_doc},
1043#endif
1044 {"close", (PyCFunction)fileio_close, METH_NOARGS, close_doc},
1045 {"seekable", (PyCFunction)fileio_seekable, METH_NOARGS, seekable_doc},
1046 {"readable", (PyCFunction)fileio_readable, METH_NOARGS, readable_doc},
1047 {"writable", (PyCFunction)fileio_writable, METH_NOARGS, writable_doc},
1048 {"fileno", (PyCFunction)fileio_fileno, METH_NOARGS, fileno_doc},
1049 {"isatty", (PyCFunction)fileio_isatty, METH_NOARGS, isatty_doc},
1050 {NULL, NULL} /* sentinel */
1051};
1052
1053/* 'closed' and 'mode' are attributes for backwards compatibility reasons. */
1054
1055static PyObject *
1056get_closed(fileio *self, void *closure)
1057{
1058 return PyBool_FromLong((long)(self->fd < 0));
1059}
1060
1061static PyObject *
1062get_closefd(fileio *self, void *closure)
1063{
1064 return PyBool_FromLong((long)(self->closefd));
1065}
1066
1067static PyObject *
1068get_mode(fileio *self, void *closure)
1069{
1070 return PyUnicode_FromString(mode_string(self));
1071}
1072
1073static PyGetSetDef fileio_getsetlist[] = {
1074 {"closed", (getter)get_closed, NULL, "True if the file is closed"},
1075 {"closefd", (getter)get_closefd, NULL,
1076 "True if the file descriptor will be closed"},
1077 {"mode", (getter)get_mode, NULL, "String giving the file mode"},
1078 {NULL},
1079};
1080
1081PyTypeObject PyFileIO_Type = {
1082 PyVarObject_HEAD_INIT(NULL, 0)
1083 "_io.FileIO",
1084 sizeof(fileio),
1085 0,
1086 (destructor)fileio_dealloc, /* tp_dealloc */
1087 0, /* tp_print */
1088 0, /* tp_getattr */
1089 0, /* tp_setattr */
1090 0, /* tp_reserved */
1091 (reprfunc)fileio_repr, /* tp_repr */
1092 0, /* tp_as_number */
1093 0, /* tp_as_sequence */
1094 0, /* tp_as_mapping */
1095 0, /* tp_hash */
1096 0, /* tp_call */
1097 0, /* tp_str */
1098 PyObject_GenericGetAttr, /* tp_getattro */
1099 0, /* tp_setattro */
1100 0, /* tp_as_buffer */
1101 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
1102 | Py_TPFLAGS_HAVE_GC, /* tp_flags */
1103 fileio_doc, /* tp_doc */
1104 (traverseproc)fileio_traverse, /* tp_traverse */
1105 (inquiry)fileio_clear, /* tp_clear */
1106 0, /* tp_richcompare */
1107 offsetof(fileio, weakreflist), /* tp_weaklistoffset */
1108 0, /* tp_iter */
1109 0, /* tp_iternext */
1110 fileio_methods, /* tp_methods */
1111 0, /* tp_members */
1112 fileio_getsetlist, /* tp_getset */
1113 0, /* tp_base */
1114 0, /* tp_dict */
1115 0, /* tp_descr_get */
1116 0, /* tp_descr_set */
1117 offsetof(fileio, dict), /* tp_dictoffset */
1118 fileio_init, /* tp_init */
1119 PyType_GenericAlloc, /* tp_alloc */
1120 fileio_new, /* tp_new */
1121 PyObject_GC_Del, /* tp_free */
1122};
Note: See TracBrowser for help on using the repository browser.