blob: 8f174a7edb573cb18b179e97eb47f963ec3eeb77 [file] [log] [blame]
Christian Heimes7f39c9f2008-01-25 12:18:43 +00001/* Author: Daniel Stutzbach */
2
3#define PY_SSIZE_T_CLEAN
4#include "Python.h"
Andrew M. Kuchling4b81bc72010-02-22 23:12:00 +00005#ifdef HAVE_SYS_TYPES_H
Christian Heimes7f39c9f2008-01-25 12:18:43 +00006#include <sys/types.h>
Andrew M. Kuchling4b81bc72010-02-22 23:12:00 +00007#endif
8#ifdef HAVE_SYS_STAT_H
Christian Heimes7f39c9f2008-01-25 12:18:43 +00009#include <sys/stat.h>
Andrew M. Kuchling4b81bc72010-02-22 23:12:00 +000010#endif
11#ifdef HAVE_FCNTL_H
Christian Heimes7f39c9f2008-01-25 12:18:43 +000012#include <fcntl.h>
Andrew M. Kuchling4b81bc72010-02-22 23:12:00 +000013#endif
Christian Heimes7f39c9f2008-01-25 12:18:43 +000014#include <stddef.h> /* For offsetof */
Antoine Pitrou19690592009-06-12 20:14:08 +000015#include "_iomodule.h"
Christian Heimes7f39c9f2008-01-25 12:18:43 +000016
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
Antoine Pitrou19690592009-06-12 20:14:08 +000037#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
Christian Heimes7f39c9f2008-01-25 12:18:43 +000051typedef struct {
52 PyObject_HEAD
53 int fd;
Antoine Pitrou2a466582009-09-21 21:17:48 +000054 unsigned int readable : 1;
55 unsigned int writable : 1;
56 signed int seekable : 2; /* -1 means unknown */
57 unsigned int closefd : 1;
Christian Heimes7f39c9f2008-01-25 12:18:43 +000058 PyObject *weakreflist;
Antoine Pitrou19690592009-06-12 20:14:08 +000059 PyObject *dict;
60} fileio;
Christian Heimes7f39c9f2008-01-25 12:18:43 +000061
62PyTypeObject PyFileIO_Type;
63
64#define PyFileIO_Check(op) (PyObject_TypeCheck((op), &PyFileIO_Type))
65
Antoine Pitrou19690592009-06-12 20:14:08 +000066int
67_PyFileIO_closed(PyObject *self)
68{
69 return ((fileio *)self)->fd < 0;
70}
71
Antoine Pitroue741cc62009-01-21 00:45:36 +000072static PyObject *
73portable_lseek(int fd, PyObject *posobj, int whence);
74
Antoine Pitrou19690592009-06-12 20:14:08 +000075static PyObject *portable_lseek(int fd, PyObject *posobj, int whence);
76
77/* Returns 0 on success, -1 with exception set on failure. */
Christian Heimes7f39c9f2008-01-25 12:18:43 +000078static int
Antoine Pitrou19690592009-06-12 20:14:08 +000079internal_close(fileio *self)
Christian Heimes7f39c9f2008-01-25 12:18:43 +000080{
Antoine Pitrou19690592009-06-12 20:14:08 +000081 int err = 0;
Christian Heimes7f39c9f2008-01-25 12:18:43 +000082 int save_errno = 0;
83 if (self->fd >= 0) {
84 int fd = self->fd;
85 self->fd = -1;
Antoine Pitrou19690592009-06-12 20:14:08 +000086 /* 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 {
Christian Heimes7f39c9f2008-01-25 12:18:43 +000094 save_errno = errno;
Antoine Pitrou19690592009-06-12 20:14:08 +000095 err = -1;
96 }
Christian Heimes7f39c9f2008-01-25 12:18:43 +000097 }
Antoine Pitrou19690592009-06-12 20:14:08 +000098 if (err < 0) {
99 errno = save_errno;
100 PyErr_SetFromErrno(PyExc_IOError);
101 return -1;
102 }
103 return 0;
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000104}
105
106static PyObject *
Antoine Pitrou19690592009-06-12 20:14:08 +0000107fileio_close(fileio *self)
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000108{
109 if (!self->closefd) {
Amaury Forgeot d'Arc32265652008-11-20 23:34:31 +0000110 self->fd = -1;
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000111 Py_RETURN_NONE;
112 }
113 errno = internal_close(self);
Antoine Pitrou19690592009-06-12 20:14:08 +0000114 if (errno < 0)
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000115 return NULL;
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000116
Antoine Pitrou19690592009-06-12 20:14:08 +0000117 return PyObject_CallMethod((PyObject*)&PyRawIOBase_Type,
118 "close", "O", self);
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000119}
120
121static PyObject *
Antoine Pitrou19690592009-06-12 20:14:08 +0000122fileio_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000123{
Antoine Pitrou19690592009-06-12 20:14:08 +0000124 fileio *self;
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000125
126 assert(type != NULL && type->tp_alloc != NULL);
127
Antoine Pitrou19690592009-06-12 20:14:08 +0000128 self = (fileio *) type->tp_alloc(type, 0);
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000129 if (self != NULL) {
130 self->fd = -1;
Christian Heimesab5f8792008-10-30 21:26:15 +0000131 self->readable = 0;
132 self->writable = 0;
133 self->seekable = -1;
134 self->closefd = 1;
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000135 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
145static int
Antoine Pitrou19690592009-06-12 20:14:08 +0000146dircheck(fileio* self, const char *name)
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000147{
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)) {
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000153 char *msg = strerror(EISDIR);
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000154 PyObject *exc;
Antoine Pitrou19690592009-06-12 20:14:08 +0000155 if (internal_close(self))
156 return -1;
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000157
Benjamin Peterson7af65562008-12-29 17:56:58 +0000158 exc = PyObject_CallFunction(PyExc_IOError, "(iss)",
159 EISDIR, msg, name);
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000160 PyErr_SetObject(PyExc_IOError, exc);
161 Py_XDECREF(exc);
162 return -1;
163 }
164#endif
165 return 0;
166}
167
Benjamin Peterson5848d1f2009-01-19 00:08:08 +0000168static int
169check_fd(int fd)
170{
171#if defined(HAVE_FSTAT)
172 struct stat buf;
Kristján Valur Jónsson6a743d32009-02-10 13:32:24 +0000173 if (!_PyVerify_fd(fd) || (fstat(fd, &buf) < 0 && errno == EBADF)) {
Benjamin Peterson5848d1f2009-01-19 00:08:08 +0000174 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
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000186
187static int
188fileio_init(PyObject *oself, PyObject *args, PyObject *kwds)
189{
Antoine Pitrou19690592009-06-12 20:14:08 +0000190 fileio *self = (fileio *) oself;
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000191 static char *kwlist[] = {"file", "mode", "closefd", NULL};
Antoine Pitrou19690592009-06-12 20:14:08 +0000192 const char *name = NULL;
193 PyObject *nameobj, *stringobj = NULL;
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000194 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
Antoine Pitrou19690592009-06-12 20:14:08 +0000212 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()) {
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000225 PyErr_SetString(PyExc_ValueError,
226 "Negative filedescriptor");
227 return -1;
228 }
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000229 PyErr_Clear();
Antoine Pitrou19690592009-06-12 20:14:08 +0000230 }
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000231
Hirokazu Yamamotob24bb272009-05-17 02:52:09 +0000232#ifdef MS_WINDOWS
Hirokazu Yamamotoa3c56092009-06-28 10:23:00 +0000233 if (PyUnicode_Check(nameobj))
234 widename = PyUnicode_AS_UNICODE(nameobj);
Antoine Pitrou19690592009-06-12 20:14:08 +0000235 if (widename == NULL)
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000236#endif
Antoine Pitrou19690592009-06-12 20:14:08 +0000237 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, "surrogateescape");
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 }
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000262 }
263
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000264 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 mode");
272 goto error;
273 }
274 rwa = 1;
275 self->readable = 1;
276 break;
277 case 'w':
278 if (rwa)
279 goto bad_mode;
280 rwa = 1;
281 self->writable = 1;
282 flags |= O_CREAT | O_TRUNC;
283 break;
284 case 'a':
285 if (rwa)
286 goto bad_mode;
287 rwa = 1;
288 self->writable = 1;
289 flags |= O_CREAT;
290 append = 1;
291 break;
Benjamin Petersonbfc51562008-11-22 01:59:15 +0000292 case 'b':
293 break;
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000294 case '+':
295 if (plus)
296 goto bad_mode;
297 self->readable = self->writable = 1;
298 plus = 1;
299 break;
300 default:
301 PyErr_Format(PyExc_ValueError,
302 "invalid mode: %.200s", mode);
303 goto error;
304 }
305 }
306
307 if (!rwa)
308 goto bad_mode;
309
310 if (self->readable && self->writable)
311 flags |= O_RDWR;
312 else if (self->readable)
313 flags |= O_RDONLY;
314 else
315 flags |= O_WRONLY;
316
317#ifdef O_BINARY
318 flags |= O_BINARY;
319#endif
320
321#ifdef O_APPEND
322 if (append)
323 flags |= O_APPEND;
324#endif
325
326 if (fd >= 0) {
Antoine Pitrou19690592009-06-12 20:14:08 +0000327 if (check_fd(fd))
328 goto error;
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000329 self->fd = fd;
330 self->closefd = closefd;
331 }
332 else {
333 self->closefd = 1;
334 if (!closefd) {
335 PyErr_SetString(PyExc_ValueError,
Amaury Forgeot d'Arc9f616f42008-10-29 23:15:57 +0000336 "Cannot use closefd=False with file name");
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000337 goto error;
338 }
339
340 Py_BEGIN_ALLOW_THREADS
341 errno = 0;
342#ifdef MS_WINDOWS
343 if (widename != NULL)
344 self->fd = _wopen(widename, flags, 0666);
345 else
346#endif
347 self->fd = open(name, flags, 0666);
348 Py_END_ALLOW_THREADS
Benjamin Petersonf22c26e2008-09-01 14:13:43 +0000349 if (self->fd < 0) {
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000350#ifdef MS_WINDOWS
Hirokazu Yamamoto99a1b202009-01-01 15:45:39 +0000351 if (widename != NULL)
352 PyErr_SetFromErrnoWithUnicodeFilename(PyExc_IOError, widename);
353 else
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000354#endif
Hirokazu Yamamoto99a1b202009-01-01 15:45:39 +0000355 PyErr_SetFromErrnoWithFilename(PyExc_IOError, name);
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000356 goto error;
357 }
Benjamin Peterson7af65562008-12-29 17:56:58 +0000358 if(dircheck(self, name) < 0)
Benjamin Petersonf22c26e2008-09-01 14:13:43 +0000359 goto error;
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000360 }
361
Antoine Pitrou19690592009-06-12 20:14:08 +0000362 if (PyObject_SetAttrString((PyObject *)self, "name", nameobj) < 0)
363 goto error;
364
Antoine Pitroue741cc62009-01-21 00:45:36 +0000365 if (append) {
366 /* For consistent behaviour, we explicitly seek to the
367 end of file (otherwise, it might be done only on the
368 first write()). */
369 PyObject *pos = portable_lseek(self->fd, NULL, 2);
370 if (pos == NULL)
371 goto error;
372 Py_DECREF(pos);
373 }
374
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000375 goto done;
376
377 error:
378 ret = -1;
379
380 done:
Antoine Pitrou19690592009-06-12 20:14:08 +0000381 Py_CLEAR(stringobj);
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000382 return ret;
383}
384
Antoine Pitrou19690592009-06-12 20:14:08 +0000385static int
386fileio_traverse(fileio *self, visitproc visit, void *arg)
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000387{
Antoine Pitrou19690592009-06-12 20:14:08 +0000388 Py_VISIT(self->dict);
389 return 0;
390}
391
392static int
393fileio_clear(fileio *self)
394{
395 Py_CLEAR(self->dict);
396 return 0;
397}
398
399static void
400fileio_dealloc(fileio *self)
401{
402 if (_PyIOBase_finalize((PyObject *) self) < 0)
403 return;
404 _PyObject_GC_UNTRACK(self);
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000405 if (self->weakreflist != NULL)
406 PyObject_ClearWeakRefs((PyObject *) self);
Antoine Pitrou19690592009-06-12 20:14:08 +0000407 Py_CLEAR(self->dict);
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000408 Py_TYPE(self)->tp_free((PyObject *)self);
409}
410
411static PyObject *
412err_closed(void)
413{
414 PyErr_SetString(PyExc_ValueError, "I/O operation on closed file");
415 return NULL;
416}
417
418static PyObject *
419err_mode(char *action)
420{
421 PyErr_Format(PyExc_ValueError, "File not open for %s", action);
422 return NULL;
423}
424
425static PyObject *
Antoine Pitrou19690592009-06-12 20:14:08 +0000426fileio_fileno(fileio *self)
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000427{
428 if (self->fd < 0)
429 return err_closed();
430 return PyInt_FromLong((long) self->fd);
431}
432
433static PyObject *
Antoine Pitrou19690592009-06-12 20:14:08 +0000434fileio_readable(fileio *self)
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000435{
436 if (self->fd < 0)
437 return err_closed();
438 return PyBool_FromLong((long) self->readable);
439}
440
441static PyObject *
Antoine Pitrou19690592009-06-12 20:14:08 +0000442fileio_writable(fileio *self)
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000443{
444 if (self->fd < 0)
445 return err_closed();
446 return PyBool_FromLong((long) self->writable);
447}
448
449static PyObject *
Antoine Pitrou19690592009-06-12 20:14:08 +0000450fileio_seekable(fileio *self)
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000451{
452 if (self->fd < 0)
453 return err_closed();
454 if (self->seekable < 0) {
Antoine Pitrou19690592009-06-12 20:14:08 +0000455 PyObject *pos = portable_lseek(self->fd, NULL, SEEK_CUR);
456 if (pos == NULL) {
457 PyErr_Clear();
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000458 self->seekable = 0;
Antoine Pitrou19690592009-06-12 20:14:08 +0000459 } else {
460 Py_DECREF(pos);
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000461 self->seekable = 1;
Antoine Pitrou19690592009-06-12 20:14:08 +0000462 }
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000463 }
464 return PyBool_FromLong((long) self->seekable);
465}
466
Antoine Pitrou16e026c2010-04-10 22:43:05 +0000467static Py_ssize_t
468internal_read(int fd, void *buf, size_t count)
469{
470 Py_ssize_t n;
471
472 Py_BEGIN_ALLOW_THREADS
473 errno = 0;
474 n = read(fd, buf, count);
475#ifdef EIO
476 /* Issue #5380: when reading past the end of a pipe created by
477 openpty(), EIO can be set. Make it an EOF instead, so that
478 the normal technique of testing for an empty string can be used.
479 */
480 if (n == -1 && errno == EIO) {
481 if (isatty(fd)) {
482 n = 0;
483 errno = 0;
484 }
485 else {
486 /* isatty() set errno, restore its value */
487 errno = EIO;
488 }
489 }
490#endif
491 Py_END_ALLOW_THREADS
492 return n;
493}
494
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000495static PyObject *
Antoine Pitrou19690592009-06-12 20:14:08 +0000496fileio_readinto(fileio *self, PyObject *args)
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000497{
Martin v. Löwisf91d46a2008-08-12 14:49:50 +0000498 Py_buffer pbuf;
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000499 Py_ssize_t n;
500
501 if (self->fd < 0)
502 return err_closed();
503 if (!self->readable)
504 return err_mode("reading");
505
Martin v. Löwisf91d46a2008-08-12 14:49:50 +0000506 if (!PyArg_ParseTuple(args, "w*", &pbuf))
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000507 return NULL;
508
Antoine Pitrou16e026c2010-04-10 22:43:05 +0000509 if (_PyVerify_fd(self->fd))
510 n = internal_read(self->fd, pbuf.buf, pbuf.len);
511 else
Antoine Pitrou19690592009-06-12 20:14:08 +0000512 n = -1;
Martin v. Löwisf91d46a2008-08-12 14:49:50 +0000513 PyBuffer_Release(&pbuf);
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000514 if (n < 0) {
515 if (errno == EAGAIN)
516 Py_RETURN_NONE;
517 PyErr_SetFromErrno(PyExc_IOError);
518 return NULL;
519 }
520
521 return PyLong_FromSsize_t(n);
522}
523
Antoine Pitrou19690592009-06-12 20:14:08 +0000524static size_t
525new_buffersize(fileio *self, size_t currentsize)
526{
527#ifdef HAVE_FSTAT
528 off_t pos, end;
529 struct stat st;
530 if (fstat(self->fd, &st) == 0) {
531 end = st.st_size;
532 pos = lseek(self->fd, 0L, SEEK_CUR);
533 /* Files claiming a size smaller than SMALLCHUNK may
534 actually be streaming pseudo-files. In this case, we
535 apply the more aggressive algorithm below.
536 */
537 if (end >= SMALLCHUNK && end >= pos && pos >= 0) {
538 /* Add 1 so if the file were to grow we'd notice. */
539 return currentsize + end - pos + 1;
540 }
541 }
542#endif
543 if (currentsize > SMALLCHUNK) {
544 /* Keep doubling until we reach BIGCHUNK;
545 then keep adding BIGCHUNK. */
546 if (currentsize <= BIGCHUNK)
547 return currentsize + currentsize;
548 else
549 return currentsize + BIGCHUNK;
550 }
551 return currentsize + SMALLCHUNK;
552}
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000553
554static PyObject *
Antoine Pitrou19690592009-06-12 20:14:08 +0000555fileio_readall(fileio *self)
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000556{
557 PyObject *result;
558 Py_ssize_t total = 0;
559 int n;
560
Antoine Pitrou19690592009-06-12 20:14:08 +0000561 if (!_PyVerify_fd(self->fd))
562 return PyErr_SetFromErrno(PyExc_IOError);
563
564 result = PyBytes_FromStringAndSize(NULL, SMALLCHUNK);
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000565 if (result == NULL)
566 return NULL;
567
568 while (1) {
Antoine Pitrou19690592009-06-12 20:14:08 +0000569 size_t newsize = new_buffersize(self, total);
570 if (newsize > PY_SSIZE_T_MAX || newsize <= 0) {
571 PyErr_SetString(PyExc_OverflowError,
572 "unbounded read returned more bytes "
573 "than a Python string can hold ");
574 Py_DECREF(result);
575 return NULL;
576 }
577
578 if (PyBytes_GET_SIZE(result) < (Py_ssize_t)newsize) {
579 if (_PyBytes_Resize(&result, newsize) < 0) {
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000580 if (total == 0) {
581 Py_DECREF(result);
582 return NULL;
583 }
584 PyErr_Clear();
585 break;
586 }
587 }
Antoine Pitrou16e026c2010-04-10 22:43:05 +0000588 n = internal_read(self->fd,
589 PyBytes_AS_STRING(result) + total,
590 newsize - total);
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000591 if (n == 0)
592 break;
593 if (n < 0) {
594 if (total > 0)
595 break;
596 if (errno == EAGAIN) {
597 Py_DECREF(result);
598 Py_RETURN_NONE;
599 }
600 Py_DECREF(result);
601 PyErr_SetFromErrno(PyExc_IOError);
602 return NULL;
603 }
604 total += n;
605 }
606
Antoine Pitrou19690592009-06-12 20:14:08 +0000607 if (PyBytes_GET_SIZE(result) > total) {
608 if (_PyBytes_Resize(&result, total) < 0) {
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000609 /* This should never happen, but just in case */
610 Py_DECREF(result);
611 return NULL;
612 }
613 }
614 return result;
615}
616
617static PyObject *
Antoine Pitrou19690592009-06-12 20:14:08 +0000618fileio_read(fileio *self, PyObject *args)
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000619{
620 char *ptr;
621 Py_ssize_t n;
622 Py_ssize_t size = -1;
623 PyObject *bytes;
624
625 if (self->fd < 0)
626 return err_closed();
627 if (!self->readable)
628 return err_mode("reading");
629
Benjamin Petersonddd392c2009-12-13 19:19:07 +0000630 if (!PyArg_ParseTuple(args, "|O&", &_PyIO_ConvertSsize_t, &size))
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000631 return NULL;
632
633 if (size < 0) {
634 return fileio_readall(self);
635 }
636
Antoine Pitrou19690592009-06-12 20:14:08 +0000637 bytes = PyBytes_FromStringAndSize(NULL, size);
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000638 if (bytes == NULL)
639 return NULL;
Antoine Pitrou19690592009-06-12 20:14:08 +0000640 ptr = PyBytes_AS_STRING(bytes);
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000641
Antoine Pitrou16e026c2010-04-10 22:43:05 +0000642 if (_PyVerify_fd(self->fd))
643 n = internal_read(self->fd, ptr, size);
644 else
Antoine Pitrou19690592009-06-12 20:14:08 +0000645 n = -1;
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000646
647 if (n < 0) {
Antoine Pitrou19690592009-06-12 20:14:08 +0000648 Py_DECREF(bytes);
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000649 if (errno == EAGAIN)
650 Py_RETURN_NONE;
651 PyErr_SetFromErrno(PyExc_IOError);
652 return NULL;
653 }
654
655 if (n != size) {
Antoine Pitrou19690592009-06-12 20:14:08 +0000656 if (_PyBytes_Resize(&bytes, n) < 0) {
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000657 Py_DECREF(bytes);
658 return NULL;
659 }
660 }
661
662 return (PyObject *) bytes;
663}
664
665static PyObject *
Antoine Pitrou19690592009-06-12 20:14:08 +0000666fileio_write(fileio *self, PyObject *args)
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000667{
Martin v. Löwisf91d46a2008-08-12 14:49:50 +0000668 Py_buffer pbuf;
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000669 Py_ssize_t n;
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000670
671 if (self->fd < 0)
672 return err_closed();
673 if (!self->writable)
674 return err_mode("writing");
675
Martin v. Löwisf91d46a2008-08-12 14:49:50 +0000676 if (!PyArg_ParseTuple(args, "s*", &pbuf))
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000677 return NULL;
678
Antoine Pitrou19690592009-06-12 20:14:08 +0000679 if (_PyVerify_fd(self->fd)) {
680 Py_BEGIN_ALLOW_THREADS
681 errno = 0;
682 n = write(self->fd, pbuf.buf, pbuf.len);
683 Py_END_ALLOW_THREADS
684 } else
685 n = -1;
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000686
Martin v. Löwisf91d46a2008-08-12 14:49:50 +0000687 PyBuffer_Release(&pbuf);
688
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000689 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
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000701/* Cribbed from posix_lseek() */
702static PyObject *
703portable_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
Benjamin Peterson8024cec2009-01-20 14:31:08 +0000716#if SEEK_END != 2
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000717 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 }
Alexandre Vassalotti1aed6242008-05-09 21:49:43 +0000729#if defined(HAVE_LARGEFILE_SUPPORT)
730 pos = PyLong_AsLongLong(posobj);
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000731#else
Alexandre Vassalotti1aed6242008-05-09 21:49:43 +0000732 pos = PyLong_AsLong(posobj);
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000733#endif
734 if (PyErr_Occurred())
735 return NULL;
736 }
737
Antoine Pitrou19690592009-06-12 20:14:08 +0000738 if (_PyVerify_fd(fd)) {
739 Py_BEGIN_ALLOW_THREADS
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000740#if defined(MS_WIN64) || defined(MS_WINDOWS)
Antoine Pitrou19690592009-06-12 20:14:08 +0000741 res = _lseeki64(fd, pos, whence);
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000742#else
Antoine Pitrou19690592009-06-12 20:14:08 +0000743 res = lseek(fd, pos, whence);
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000744#endif
Antoine Pitrou19690592009-06-12 20:14:08 +0000745 Py_END_ALLOW_THREADS
746 } else
747 res = -1;
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000748 if (res < 0)
749 return PyErr_SetFromErrno(PyExc_IOError);
750
Alexandre Vassalotti1aed6242008-05-09 21:49:43 +0000751#if defined(HAVE_LARGEFILE_SUPPORT)
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000752 return PyLong_FromLongLong(res);
Alexandre Vassalotti1aed6242008-05-09 21:49:43 +0000753#else
754 return PyLong_FromLong(res);
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000755#endif
756}
757
758static PyObject *
Antoine Pitrou19690592009-06-12 20:14:08 +0000759fileio_seek(fileio *self, PyObject *args)
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000760{
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
773static PyObject *
Antoine Pitrou19690592009-06-12 20:14:08 +0000774fileio_tell(fileio *self, PyObject *args)
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000775{
776 if (self->fd < 0)
777 return err_closed();
778
779 return portable_lseek(self->fd, NULL, 1);
780}
781
782#ifdef HAVE_FTRUNCATE
783static PyObject *
Antoine Pitrou19690592009-06-12 20:14:08 +0000784fileio_truncate(fileio *self, PyObject *args)
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000785{
Antoine Pitrouf3fa0742010-01-31 22:26:04 +0000786 PyObject *posobj = NULL; /* the new size wanted by the user */
787#ifndef MS_WINDOWS
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000788 Py_off_t pos;
Antoine Pitrouf3fa0742010-01-31 22:26:04 +0000789#endif
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000790 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) {
Alexandre Vassalotti1aed6242008-05-09 21:49:43 +0000803 /* Get the current position. */
Antoine Pitrouf3fa0742010-01-31 22:26:04 +0000804 posobj = portable_lseek(fd, NULL, 1);
805 if (posobj == NULL)
Alexandre Vassalotti1aed6242008-05-09 21:49:43 +0000806 return NULL;
Antoine Pitrouf3fa0742010-01-31 22:26:04 +0000807 }
808 else {
809 Py_INCREF(posobj);
810 }
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000811
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 {
Antoine Pitrouf3fa0742010-01-31 22:26:04 +0000816 PyObject *oldposobj, *tempposobj;
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000817 HANDLE hFile;
Antoine Pitrouf3fa0742010-01-31 22:26:04 +0000818
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);
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000834
835 /* Truncate. Note that this may grow the file! */
836 Py_BEGIN_ALLOW_THREADS
837 errno = 0;
838 hFile = (HANDLE)_get_osfhandle(fd);
Antoine Pitrouf3fa0742010-01-31 22:26:04 +0000839 ret = hFile == (HANDLE)-1; /* testing for INVALID_HANDLE value */
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000840 if (ret == 0) {
841 ret = SetEndOfFile(hFile) == 0;
842 if (ret)
843 errno = EACCES;
844 }
845 Py_END_ALLOW_THREADS
Antoine Pitrouf3fa0742010-01-31 22:26:04 +0000846
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);
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000855 }
856#else
Antoine Pitrouf3fa0742010-01-31 22:26:04 +0000857
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
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000868 Py_BEGIN_ALLOW_THREADS
869 errno = 0;
870 ret = ftruncate(fd, pos);
871 Py_END_ALLOW_THREADS
Antoine Pitrouf3fa0742010-01-31 22:26:04 +0000872
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000873#endif /* !MS_WINDOWS */
874
875 if (ret != 0) {
Antoine Pitrouf3fa0742010-01-31 22:26:04 +0000876 Py_DECREF(posobj);
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000877 PyErr_SetFromErrno(PyExc_IOError);
878 return NULL;
879 }
880
881 return posobj;
882}
Antoine Pitrouf3fa0742010-01-31 22:26:04 +0000883#endif /* HAVE_FTRUNCATE */
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000884
885static char *
Antoine Pitrou19690592009-06-12 20:14:08 +0000886mode_string(fileio *self)
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000887{
888 if (self->readable) {
889 if (self->writable)
Benjamin Petersonbfc51562008-11-22 01:59:15 +0000890 return "rb+";
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000891 else
Benjamin Petersonbfc51562008-11-22 01:59:15 +0000892 return "rb";
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000893 }
894 else
Benjamin Petersonbfc51562008-11-22 01:59:15 +0000895 return "wb";
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000896}
897
898static PyObject *
Antoine Pitrou19690592009-06-12 20:14:08 +0000899fileio_repr(fileio *self)
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000900{
Antoine Pitrou19690592009-06-12 20:14:08 +0000901 PyObject *nameobj, *res;
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000902
Antoine Pitrou19690592009-06-12 20:14:08 +0000903 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;
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000926}
927
928static PyObject *
Antoine Pitrou19690592009-06-12 20:14:08 +0000929fileio_isatty(fileio *self)
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000930{
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
942PyDoc_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
951PyDoc_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
958PyDoc_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
964PyDoc_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
970PyDoc_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
975PyDoc_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
987PyDoc_STRVAR(truncate_doc,
988"truncate([size: int]) -> None. Truncate the file to at most size bytes.\n"
989"\n"
Alexandre Vassalotti1aed6242008-05-09 21:49:43 +0000990"Size defaults to the current file position, as returned by tell()."
991"The current file position is changed to the value of size.");
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000992#endif
993
994PyDoc_STRVAR(tell_doc,
995"tell() -> int. Current file position");
996
997PyDoc_STRVAR(readinto_doc,
Antoine Pitrou19690592009-06-12 20:14:08 +0000998"readinto() -> Same as RawIOBase.readinto().");
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000999
1000PyDoc_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
1006PyDoc_STRVAR(isatty_doc,
1007"isatty() -> bool. True if the file is connected to a tty device.");
1008
1009PyDoc_STRVAR(seekable_doc,
1010"seekable() -> bool. True if file supports random-access.");
1011
1012PyDoc_STRVAR(readable_doc,
1013"readable() -> bool. True if file was opened in a read mode.");
1014
1015PyDoc_STRVAR(writable_doc,
1016"writable() -> bool. True if file was opened in a write mode.");
1017
1018static 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
1039static PyObject *
Antoine Pitrou19690592009-06-12 20:14:08 +00001040get_closed(fileio *self, void *closure)
Christian Heimes7f39c9f2008-01-25 12:18:43 +00001041{
1042 return PyBool_FromLong((long)(self->fd < 0));
1043}
1044
1045static PyObject *
Antoine Pitrou19690592009-06-12 20:14:08 +00001046get_closefd(fileio *self, void *closure)
Amaury Forgeot d'Arc32265652008-11-20 23:34:31 +00001047{
1048 return PyBool_FromLong((long)(self->closefd));
1049}
1050
1051static PyObject *
Antoine Pitrou19690592009-06-12 20:14:08 +00001052get_mode(fileio *self, void *closure)
Christian Heimes7f39c9f2008-01-25 12:18:43 +00001053{
Antoine Pitrou19690592009-06-12 20:14:08 +00001054 return PyUnicode_FromString(mode_string(self));
Christian Heimes7f39c9f2008-01-25 12:18:43 +00001055}
1056
1057static PyGetSetDef fileio_getsetlist[] = {
1058 {"closed", (getter)get_closed, NULL, "True if the file is closed"},
Amaury Forgeot d'Arc32265652008-11-20 23:34:31 +00001059 {"closefd", (getter)get_closefd, NULL,
1060 "True if the file descriptor will be closed"},
Christian Heimes7f39c9f2008-01-25 12:18:43 +00001061 {"mode", (getter)get_mode, NULL, "String giving the file mode"},
Antoine Pitrou19690592009-06-12 20:14:08 +00001062 {NULL},
Christian Heimes7f39c9f2008-01-25 12:18:43 +00001063};
1064
1065PyTypeObject PyFileIO_Type = {
Hirokazu Yamamoto09979a12008-09-23 16:11:09 +00001066 PyVarObject_HEAD_INIT(NULL, 0)
Antoine Pitrou19690592009-06-12 20:14:08 +00001067 "_io.FileIO",
1068 sizeof(fileio),
Christian Heimes7f39c9f2008-01-25 12:18:43 +00001069 0,
1070 (destructor)fileio_dealloc, /* tp_dealloc */
1071 0, /* tp_print */
1072 0, /* tp_getattr */
1073 0, /* tp_setattr */
Antoine Pitrou19690592009-06-12 20:14:08 +00001074 0, /* tp_reserved */
Christian Heimes7f39c9f2008-01-25 12:18:43 +00001075 (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 */
Antoine Pitrou19690592009-06-12 20:14:08 +00001085 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
1086 | Py_TPFLAGS_HAVE_GC, /* tp_flags */
Christian Heimes7f39c9f2008-01-25 12:18:43 +00001087 fileio_doc, /* tp_doc */
Antoine Pitrou19690592009-06-12 20:14:08 +00001088 (traverseproc)fileio_traverse, /* tp_traverse */
1089 (inquiry)fileio_clear, /* tp_clear */
Christian Heimes7f39c9f2008-01-25 12:18:43 +00001090 0, /* tp_richcompare */
Antoine Pitrou19690592009-06-12 20:14:08 +00001091 offsetof(fileio, weakreflist), /* tp_weaklistoffset */
Christian Heimes7f39c9f2008-01-25 12:18:43 +00001092 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 */
Antoine Pitrou19690592009-06-12 20:14:08 +00001101 offsetof(fileio, dict), /* tp_dictoffset */
Christian Heimes7f39c9f2008-01-25 12:18:43 +00001102 fileio_init, /* tp_init */
1103 PyType_GenericAlloc, /* tp_alloc */
1104 fileio_new, /* tp_new */
Antoine Pitrou19690592009-06-12 20:14:08 +00001105 PyObject_GC_Del, /* tp_free */
Christian Heimes7f39c9f2008-01-25 12:18:43 +00001106};