blob: 0048240b791085bedf3ee6f57e459ff65a8ed635 [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
Christian Heimes7f39c9f2008-01-25 12:18:43 +000045typedef struct {
Antoine Pitroub26dc462010-05-05 16:27:30 +000046 PyObject_HEAD
47 int fd;
48 unsigned int readable : 1;
49 unsigned int writable : 1;
50 signed int seekable : 2; /* -1 means unknown */
51 unsigned int closefd : 1;
52 PyObject *weakreflist;
53 PyObject *dict;
Antoine Pitrou19690592009-06-12 20:14:08 +000054} fileio;
Christian Heimes7f39c9f2008-01-25 12:18:43 +000055
56PyTypeObject PyFileIO_Type;
57
58#define PyFileIO_Check(op) (PyObject_TypeCheck((op), &PyFileIO_Type))
59
Antoine Pitrou19690592009-06-12 20:14:08 +000060int
61_PyFileIO_closed(PyObject *self)
62{
Antoine Pitroub26dc462010-05-05 16:27:30 +000063 return ((fileio *)self)->fd < 0;
Antoine Pitrou19690592009-06-12 20:14:08 +000064}
65
Antoine Pitroue741cc62009-01-21 00:45:36 +000066static PyObject *
67portable_lseek(int fd, PyObject *posobj, int whence);
68
Antoine Pitrou19690592009-06-12 20:14:08 +000069static PyObject *portable_lseek(int fd, PyObject *posobj, int whence);
70
71/* Returns 0 on success, -1 with exception set on failure. */
Christian Heimes7f39c9f2008-01-25 12:18:43 +000072static int
Antoine Pitrou19690592009-06-12 20:14:08 +000073internal_close(fileio *self)
Christian Heimes7f39c9f2008-01-25 12:18:43 +000074{
Antoine Pitroub26dc462010-05-05 16:27:30 +000075 int err = 0;
76 int save_errno = 0;
77 if (self->fd >= 0) {
78 int fd = self->fd;
79 self->fd = -1;
80 /* fd is accessible and someone else may have closed it */
81 if (_PyVerify_fd(fd)) {
82 Py_BEGIN_ALLOW_THREADS
83 err = close(fd);
84 if (err < 0)
85 save_errno = errno;
86 Py_END_ALLOW_THREADS
87 } else {
88 save_errno = errno;
89 err = -1;
90 }
91 }
92 if (err < 0) {
93 errno = save_errno;
94 PyErr_SetFromErrno(PyExc_IOError);
95 return -1;
96 }
97 return 0;
Christian Heimes7f39c9f2008-01-25 12:18:43 +000098}
99
100static PyObject *
Antoine Pitrou19690592009-06-12 20:14:08 +0000101fileio_close(fileio *self)
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000102{
Antoine Pitroub26dc462010-05-05 16:27:30 +0000103 if (!self->closefd) {
104 self->fd = -1;
105 Py_RETURN_NONE;
106 }
107 errno = internal_close(self);
108 if (errno < 0)
109 return NULL;
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000110
Antoine Pitroub26dc462010-05-05 16:27:30 +0000111 return PyObject_CallMethod((PyObject*)&PyRawIOBase_Type,
112 "close", "O", self);
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000113}
114
115static PyObject *
Antoine Pitrou19690592009-06-12 20:14:08 +0000116fileio_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000117{
Antoine Pitroub26dc462010-05-05 16:27:30 +0000118 fileio *self;
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000119
Antoine Pitroub26dc462010-05-05 16:27:30 +0000120 assert(type != NULL && type->tp_alloc != NULL);
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000121
Antoine Pitroub26dc462010-05-05 16:27:30 +0000122 self = (fileio *) type->tp_alloc(type, 0);
123 if (self != NULL) {
124 self->fd = -1;
125 self->readable = 0;
126 self->writable = 0;
127 self->seekable = -1;
128 self->closefd = 1;
129 self->weakreflist = NULL;
130 }
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000131
Antoine Pitroub26dc462010-05-05 16:27:30 +0000132 return (PyObject *) self;
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000133}
134
135/* On Unix, open will succeed for directories.
136 In Python, there should be no file objects referring to
137 directories, so we need a check. */
138
139static int
Antoine Pitrou19690592009-06-12 20:14:08 +0000140dircheck(fileio* self, const char *name)
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000141{
142#if defined(HAVE_FSTAT) && defined(S_IFDIR) && defined(EISDIR)
Antoine Pitroub26dc462010-05-05 16:27:30 +0000143 struct stat buf;
144 if (self->fd < 0)
145 return 0;
146 if (fstat(self->fd, &buf) == 0 && S_ISDIR(buf.st_mode)) {
147 char *msg = strerror(EISDIR);
148 PyObject *exc;
149 if (internal_close(self))
150 return -1;
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000151
Antoine Pitroub26dc462010-05-05 16:27:30 +0000152 exc = PyObject_CallFunction(PyExc_IOError, "(iss)",
153 EISDIR, msg, name);
154 PyErr_SetObject(PyExc_IOError, exc);
155 Py_XDECREF(exc);
156 return -1;
157 }
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000158#endif
Antoine Pitroub26dc462010-05-05 16:27:30 +0000159 return 0;
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000160}
161
Benjamin Peterson5848d1f2009-01-19 00:08:08 +0000162static int
163check_fd(int fd)
164{
165#if defined(HAVE_FSTAT)
Antoine Pitroub26dc462010-05-05 16:27:30 +0000166 struct stat buf;
167 if (!_PyVerify_fd(fd) || (fstat(fd, &buf) < 0 && errno == EBADF)) {
168 PyObject *exc;
169 char *msg = strerror(EBADF);
170 exc = PyObject_CallFunction(PyExc_OSError, "(is)",
171 EBADF, msg);
172 PyErr_SetObject(PyExc_OSError, exc);
173 Py_XDECREF(exc);
174 return -1;
175 }
Benjamin Peterson5848d1f2009-01-19 00:08:08 +0000176#endif
Antoine Pitroub26dc462010-05-05 16:27:30 +0000177 return 0;
Benjamin Peterson5848d1f2009-01-19 00:08:08 +0000178}
179
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000180
181static int
182fileio_init(PyObject *oself, PyObject *args, PyObject *kwds)
183{
Antoine Pitroub26dc462010-05-05 16:27:30 +0000184 fileio *self = (fileio *) oself;
185 static char *kwlist[] = {"file", "mode", "closefd", NULL};
186 const char *name = NULL;
187 PyObject *nameobj, *stringobj = NULL;
188 char *mode = "r";
189 char *s;
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000190#ifdef MS_WINDOWS
Antoine Pitroub26dc462010-05-05 16:27:30 +0000191 Py_UNICODE *widename = NULL;
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000192#endif
Antoine Pitroub26dc462010-05-05 16:27:30 +0000193 int ret = 0;
194 int rwa = 0, plus = 0, append = 0;
195 int flags = 0;
196 int fd = -1;
197 int closefd = 1;
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000198
Antoine Pitroub26dc462010-05-05 16:27:30 +0000199 assert(PyFileIO_Check(oself));
200 if (self->fd >= 0) {
201 /* Have to close the existing file first. */
202 if (internal_close(self) < 0)
203 return -1;
204 }
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000205
Antoine Pitroub26dc462010-05-05 16:27:30 +0000206 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|si:fileio",
207 kwlist, &nameobj, &mode, &closefd))
208 return -1;
Antoine Pitrou19690592009-06-12 20:14:08 +0000209
Antoine Pitroub26dc462010-05-05 16:27:30 +0000210 if (PyFloat_Check(nameobj)) {
211 PyErr_SetString(PyExc_TypeError,
212 "integer argument expected, got float");
213 return -1;
214 }
Antoine Pitrou19690592009-06-12 20:14:08 +0000215
Antoine Pitroub26dc462010-05-05 16:27:30 +0000216 fd = PyLong_AsLong(nameobj);
217 if (fd < 0) {
218 if (!PyErr_Occurred()) {
219 PyErr_SetString(PyExc_ValueError,
220 "Negative filedescriptor");
221 return -1;
222 }
223 PyErr_Clear();
224 }
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000225
Hirokazu Yamamotob24bb272009-05-17 02:52:09 +0000226#ifdef MS_WINDOWS
Antoine Pitroub26dc462010-05-05 16:27:30 +0000227 if (PyUnicode_Check(nameobj))
228 widename = PyUnicode_AS_UNICODE(nameobj);
229 if (widename == NULL)
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000230#endif
Antoine Pitroub26dc462010-05-05 16:27:30 +0000231 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);
Antoine Pitrou19690592009-06-12 20:14:08 +0000240
Antoine Pitroub26dc462010-05-05 16:27:30 +0000241 if (u == NULL)
242 return -1;
Antoine Pitrou19690592009-06-12 20:14:08 +0000243
Antoine Pitroub26dc462010-05-05 16:27:30 +0000244 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 }
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000257
Antoine Pitroub26dc462010-05-05 16:27:30 +0000258 s = mode;
259 while (*s) {
260 switch (*s++) {
261 case 'r':
262 if (rwa) {
263 bad_mode:
264 PyErr_SetString(PyExc_ValueError,
Georg Brandl10603802010-11-26 08:10:41 +0000265 "Must have exactly one of read/write/append "
266 "mode and at most one plus");
Antoine Pitroub26dc462010-05-05 16:27:30 +0000267 goto error;
268 }
269 rwa = 1;
270 self->readable = 1;
271 break;
272 case 'w':
273 if (rwa)
274 goto bad_mode;
275 rwa = 1;
276 self->writable = 1;
277 flags |= O_CREAT | O_TRUNC;
278 break;
279 case 'a':
280 if (rwa)
281 goto bad_mode;
282 rwa = 1;
283 self->writable = 1;
284 flags |= O_CREAT;
285 append = 1;
286 break;
287 case 'b':
288 break;
289 case '+':
290 if (plus)
291 goto bad_mode;
292 self->readable = self->writable = 1;
293 plus = 1;
294 break;
295 default:
296 PyErr_Format(PyExc_ValueError,
297 "invalid mode: %.200s", mode);
298 goto error;
299 }
300 }
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000301
Antoine Pitroub26dc462010-05-05 16:27:30 +0000302 if (!rwa)
303 goto bad_mode;
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000304
Antoine Pitroub26dc462010-05-05 16:27:30 +0000305 if (self->readable && self->writable)
306 flags |= O_RDWR;
307 else if (self->readable)
308 flags |= O_RDONLY;
309 else
310 flags |= O_WRONLY;
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000311
312#ifdef O_BINARY
Antoine Pitroub26dc462010-05-05 16:27:30 +0000313 flags |= O_BINARY;
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000314#endif
315
316#ifdef O_APPEND
Antoine Pitroub26dc462010-05-05 16:27:30 +0000317 if (append)
318 flags |= O_APPEND;
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000319#endif
320
Antoine Pitroub26dc462010-05-05 16:27:30 +0000321 if (fd >= 0) {
322 if (check_fd(fd))
323 goto error;
324 self->fd = fd;
325 self->closefd = closefd;
326 }
327 else {
328 self->closefd = 1;
329 if (!closefd) {
330 PyErr_SetString(PyExc_ValueError,
331 "Cannot use closefd=False with file name");
332 goto error;
333 }
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000334
Antoine Pitroub26dc462010-05-05 16:27:30 +0000335 Py_BEGIN_ALLOW_THREADS
336 errno = 0;
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000337#ifdef MS_WINDOWS
Antoine Pitroub26dc462010-05-05 16:27:30 +0000338 if (widename != NULL)
339 self->fd = _wopen(widename, flags, 0666);
340 else
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000341#endif
Antoine Pitroub26dc462010-05-05 16:27:30 +0000342 self->fd = open(name, flags, 0666);
343 Py_END_ALLOW_THREADS
344 if (self->fd < 0) {
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000345#ifdef MS_WINDOWS
Antoine Pitroub26dc462010-05-05 16:27:30 +0000346 if (widename != NULL)
347 PyErr_SetFromErrnoWithUnicodeFilename(PyExc_IOError, widename);
348 else
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000349#endif
Antoine Pitroub26dc462010-05-05 16:27:30 +0000350 PyErr_SetFromErrnoWithFilename(PyExc_IOError, name);
351 goto error;
352 }
353 if(dircheck(self, name) < 0)
354 goto error;
355 }
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000356
Antoine Pitroub26dc462010-05-05 16:27:30 +0000357 if (PyObject_SetAttrString((PyObject *)self, "name", nameobj) < 0)
358 goto error;
Antoine Pitrou19690592009-06-12 20:14:08 +0000359
Antoine Pitroub26dc462010-05-05 16:27:30 +0000360 if (append) {
361 /* For consistent behaviour, we explicitly seek to the
362 end of file (otherwise, it might be done only on the
363 first write()). */
364 PyObject *pos = portable_lseek(self->fd, NULL, 2);
Antoine Pitrou594a0462010-10-31 13:05:48 +0000365 if (pos == NULL) {
366 if (closefd) {
367 close(self->fd);
368 self->fd = -1;
369 }
Antoine Pitroub26dc462010-05-05 16:27:30 +0000370 goto error;
Antoine Pitrou594a0462010-10-31 13:05:48 +0000371 }
Antoine Pitroub26dc462010-05-05 16:27:30 +0000372 Py_DECREF(pos);
373 }
Antoine Pitroue741cc62009-01-21 00:45:36 +0000374
Antoine Pitroub26dc462010-05-05 16:27:30 +0000375 goto done;
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000376
377 error:
Antoine Pitroub26dc462010-05-05 16:27:30 +0000378 ret = -1;
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000379
380 done:
Antoine Pitroub26dc462010-05-05 16:27:30 +0000381 Py_CLEAR(stringobj);
382 return ret;
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000383}
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 Pitroub26dc462010-05-05 16:27:30 +0000388 Py_VISIT(self->dict);
389 return 0;
Antoine Pitrou19690592009-06-12 20:14:08 +0000390}
391
392static int
393fileio_clear(fileio *self)
394{
Antoine Pitroub26dc462010-05-05 16:27:30 +0000395 Py_CLEAR(self->dict);
396 return 0;
Antoine Pitrou19690592009-06-12 20:14:08 +0000397}
398
399static void
400fileio_dealloc(fileio *self)
401{
Antoine Pitroub26dc462010-05-05 16:27:30 +0000402 if (_PyIOBase_finalize((PyObject *) self) < 0)
403 return;
404 _PyObject_GC_UNTRACK(self);
405 if (self->weakreflist != NULL)
406 PyObject_ClearWeakRefs((PyObject *) self);
407 Py_CLEAR(self->dict);
408 Py_TYPE(self)->tp_free((PyObject *)self);
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000409}
410
411static PyObject *
412err_closed(void)
413{
Antoine Pitroub26dc462010-05-05 16:27:30 +0000414 PyErr_SetString(PyExc_ValueError, "I/O operation on closed file");
415 return NULL;
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000416}
417
418static PyObject *
419err_mode(char *action)
420{
Antoine Pitroub26dc462010-05-05 16:27:30 +0000421 PyErr_Format(PyExc_ValueError, "File not open for %s", action);
422 return NULL;
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000423}
424
425static PyObject *
Antoine Pitrou19690592009-06-12 20:14:08 +0000426fileio_fileno(fileio *self)
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000427{
Antoine Pitroub26dc462010-05-05 16:27:30 +0000428 if (self->fd < 0)
429 return err_closed();
430 return PyInt_FromLong((long) self->fd);
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000431}
432
433static PyObject *
Antoine Pitrou19690592009-06-12 20:14:08 +0000434fileio_readable(fileio *self)
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000435{
Antoine Pitroub26dc462010-05-05 16:27:30 +0000436 if (self->fd < 0)
437 return err_closed();
438 return PyBool_FromLong((long) self->readable);
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000439}
440
441static PyObject *
Antoine Pitrou19690592009-06-12 20:14:08 +0000442fileio_writable(fileio *self)
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000443{
Antoine Pitroub26dc462010-05-05 16:27:30 +0000444 if (self->fd < 0)
445 return err_closed();
446 return PyBool_FromLong((long) self->writable);
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000447}
448
449static PyObject *
Antoine Pitrou19690592009-06-12 20:14:08 +0000450fileio_seekable(fileio *self)
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000451{
Antoine Pitroub26dc462010-05-05 16:27:30 +0000452 if (self->fd < 0)
453 return err_closed();
454 if (self->seekable < 0) {
455 PyObject *pos = portable_lseek(self->fd, NULL, SEEK_CUR);
456 if (pos == NULL) {
457 PyErr_Clear();
458 self->seekable = 0;
459 } else {
460 Py_DECREF(pos);
461 self->seekable = 1;
462 }
463 }
464 return PyBool_FromLong((long) self->seekable);
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000465}
466
467static PyObject *
Antoine Pitrou19690592009-06-12 20:14:08 +0000468fileio_readinto(fileio *self, PyObject *args)
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000469{
Antoine Pitroub26dc462010-05-05 16:27:30 +0000470 Py_buffer pbuf;
Victor Stinner59729ff2011-07-05 11:28:19 +0200471 Py_ssize_t n, len;
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000472
Antoine Pitroub26dc462010-05-05 16:27:30 +0000473 if (self->fd < 0)
474 return err_closed();
475 if (!self->readable)
476 return err_mode("reading");
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000477
Antoine Pitroub26dc462010-05-05 16:27:30 +0000478 if (!PyArg_ParseTuple(args, "w*", &pbuf))
479 return NULL;
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000480
Antoine Pitroub26dc462010-05-05 16:27:30 +0000481 if (_PyVerify_fd(self->fd)) {
Victor Stinner59729ff2011-07-05 11:28:19 +0200482 len = pbuf.len;
Antoine Pitroub26dc462010-05-05 16:27:30 +0000483 Py_BEGIN_ALLOW_THREADS
484 errno = 0;
Victor Stinner59729ff2011-07-05 11:28:19 +0200485#if defined(MS_WIN64) || defined(MS_WINDOWS)
486 if (len > INT_MAX)
487 len = INT_MAX;
488 n = read(self->fd, pbuf.buf, (int)len);
489#else
490 n = read(self->fd, pbuf.buf, len);
491#endif
Antoine Pitroub26dc462010-05-05 16:27:30 +0000492 Py_END_ALLOW_THREADS
493 } else
494 n = -1;
495 PyBuffer_Release(&pbuf);
496 if (n < 0) {
497 if (errno == EAGAIN)
498 Py_RETURN_NONE;
499 PyErr_SetFromErrno(PyExc_IOError);
500 return NULL;
501 }
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000502
Antoine Pitroub26dc462010-05-05 16:27:30 +0000503 return PyLong_FromSsize_t(n);
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000504}
505
Antoine Pitrou19690592009-06-12 20:14:08 +0000506static size_t
507new_buffersize(fileio *self, size_t currentsize)
508{
509#ifdef HAVE_FSTAT
Antoine Pitroub26dc462010-05-05 16:27:30 +0000510 off_t pos, end;
511 struct stat st;
512 if (fstat(self->fd, &st) == 0) {
513 end = st.st_size;
514 pos = lseek(self->fd, 0L, SEEK_CUR);
515 /* Files claiming a size smaller than SMALLCHUNK may
516 actually be streaming pseudo-files. In this case, we
517 apply the more aggressive algorithm below.
518 */
519 if (end >= SMALLCHUNK && end >= pos && pos >= 0) {
520 /* Add 1 so if the file were to grow we'd notice. */
521 return currentsize + end - pos + 1;
522 }
523 }
Antoine Pitrou19690592009-06-12 20:14:08 +0000524#endif
Nadeem Vawda36248152011-10-13 13:52:46 +0200525 /* Expand the buffer by an amount proportional to the current size,
526 giving us amortized linear-time behavior. Use a less-than-double
527 growth factor to avoid excessive allocation. */
528 return currentsize + (currentsize >> 3) + 6;
Antoine Pitrou19690592009-06-12 20:14:08 +0000529}
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000530
531static PyObject *
Antoine Pitrou19690592009-06-12 20:14:08 +0000532fileio_readall(fileio *self)
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000533{
Antoine Pitroub26dc462010-05-05 16:27:30 +0000534 PyObject *result;
535 Py_ssize_t total = 0;
536 int n;
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000537
Victor Stinner5100a402011-05-25 22:15:36 +0200538 if (self->fd < 0)
539 return err_closed();
Antoine Pitroub26dc462010-05-05 16:27:30 +0000540 if (!_PyVerify_fd(self->fd))
541 return PyErr_SetFromErrno(PyExc_IOError);
Antoine Pitrou19690592009-06-12 20:14:08 +0000542
Antoine Pitroub26dc462010-05-05 16:27:30 +0000543 result = PyBytes_FromStringAndSize(NULL, SMALLCHUNK);
544 if (result == NULL)
545 return NULL;
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000546
Antoine Pitroub26dc462010-05-05 16:27:30 +0000547 while (1) {
548 size_t newsize = new_buffersize(self, total);
549 if (newsize > PY_SSIZE_T_MAX || newsize <= 0) {
550 PyErr_SetString(PyExc_OverflowError,
551 "unbounded read returned more bytes "
552 "than a Python string can hold ");
553 Py_DECREF(result);
554 return NULL;
555 }
Antoine Pitrou19690592009-06-12 20:14:08 +0000556
Antoine Pitroub26dc462010-05-05 16:27:30 +0000557 if (PyBytes_GET_SIZE(result) < (Py_ssize_t)newsize) {
558 if (_PyBytes_Resize(&result, newsize) < 0) {
559 if (total == 0) {
560 Py_DECREF(result);
561 return NULL;
562 }
563 PyErr_Clear();
564 break;
565 }
566 }
567 Py_BEGIN_ALLOW_THREADS
568 errno = 0;
569 n = read(self->fd,
570 PyBytes_AS_STRING(result) + total,
571 newsize - total);
572 Py_END_ALLOW_THREADS
573 if (n == 0)
574 break;
575 if (n < 0) {
576 if (total > 0)
577 break;
578 if (errno == EAGAIN) {
579 Py_DECREF(result);
580 Py_RETURN_NONE;
581 }
582 Py_DECREF(result);
583 PyErr_SetFromErrno(PyExc_IOError);
584 return NULL;
585 }
586 total += n;
587 }
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000588
Antoine Pitroub26dc462010-05-05 16:27:30 +0000589 if (PyBytes_GET_SIZE(result) > total) {
590 if (_PyBytes_Resize(&result, total) < 0) {
591 /* This should never happen, but just in case */
592 Py_DECREF(result);
593 return NULL;
594 }
595 }
596 return result;
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000597}
598
599static PyObject *
Antoine Pitrou19690592009-06-12 20:14:08 +0000600fileio_read(fileio *self, PyObject *args)
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000601{
Antoine Pitroub26dc462010-05-05 16:27:30 +0000602 char *ptr;
603 Py_ssize_t n;
604 Py_ssize_t size = -1;
605 PyObject *bytes;
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000606
Antoine Pitroub26dc462010-05-05 16:27:30 +0000607 if (self->fd < 0)
608 return err_closed();
609 if (!self->readable)
610 return err_mode("reading");
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000611
Antoine Pitroub26dc462010-05-05 16:27:30 +0000612 if (!PyArg_ParseTuple(args, "|O&", &_PyIO_ConvertSsize_t, &size))
613 return NULL;
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000614
Antoine Pitroub26dc462010-05-05 16:27:30 +0000615 if (size < 0) {
616 return fileio_readall(self);
617 }
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000618
Victor Stinner59729ff2011-07-05 11:28:19 +0200619#if defined(MS_WIN64) || defined(MS_WINDOWS)
620 if (size > INT_MAX)
621 size = INT_MAX;
622#endif
Antoine Pitroub26dc462010-05-05 16:27:30 +0000623 bytes = PyBytes_FromStringAndSize(NULL, size);
624 if (bytes == NULL)
625 return NULL;
626 ptr = PyBytes_AS_STRING(bytes);
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000627
Antoine Pitroub26dc462010-05-05 16:27:30 +0000628 if (_PyVerify_fd(self->fd)) {
629 Py_BEGIN_ALLOW_THREADS
630 errno = 0;
Victor Stinner59729ff2011-07-05 11:28:19 +0200631#if defined(MS_WIN64) || defined(MS_WINDOWS)
632 n = read(self->fd, ptr, (int)size);
633#else
Antoine Pitroub26dc462010-05-05 16:27:30 +0000634 n = read(self->fd, ptr, size);
Victor Stinner59729ff2011-07-05 11:28:19 +0200635#endif
Antoine Pitroub26dc462010-05-05 16:27:30 +0000636 Py_END_ALLOW_THREADS
637 } else
638 n = -1;
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000639
Antoine Pitroub26dc462010-05-05 16:27:30 +0000640 if (n < 0) {
641 Py_DECREF(bytes);
642 if (errno == EAGAIN)
643 Py_RETURN_NONE;
644 PyErr_SetFromErrno(PyExc_IOError);
645 return NULL;
646 }
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000647
Antoine Pitroub26dc462010-05-05 16:27:30 +0000648 if (n != size) {
649 if (_PyBytes_Resize(&bytes, n) < 0) {
650 Py_DECREF(bytes);
651 return NULL;
652 }
653 }
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000654
Antoine Pitroub26dc462010-05-05 16:27:30 +0000655 return (PyObject *) bytes;
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000656}
657
658static PyObject *
Antoine Pitrou19690592009-06-12 20:14:08 +0000659fileio_write(fileio *self, PyObject *args)
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000660{
Antoine Pitroub26dc462010-05-05 16:27:30 +0000661 Py_buffer pbuf;
Victor Stinner59729ff2011-07-05 11:28:19 +0200662 Py_ssize_t n, len;
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000663
Antoine Pitroub26dc462010-05-05 16:27:30 +0000664 if (self->fd < 0)
665 return err_closed();
666 if (!self->writable)
667 return err_mode("writing");
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000668
Antoine Pitroub26dc462010-05-05 16:27:30 +0000669 if (!PyArg_ParseTuple(args, "s*", &pbuf))
670 return NULL;
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000671
Antoine Pitroub26dc462010-05-05 16:27:30 +0000672 if (_PyVerify_fd(self->fd)) {
673 Py_BEGIN_ALLOW_THREADS
674 errno = 0;
Victor Stinner59729ff2011-07-05 11:28:19 +0200675 len = pbuf.len;
676#if defined(MS_WIN64) || defined(MS_WINDOWS)
677 if (len > INT_MAX)
678 len = INT_MAX;
679 n = write(self->fd, pbuf.buf, (int)len);
680#else
681 n = write(self->fd, pbuf.buf, len);
682#endif
Antoine Pitroub26dc462010-05-05 16:27:30 +0000683 Py_END_ALLOW_THREADS
684 } else
685 n = -1;
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000686
Antoine Pitroub26dc462010-05-05 16:27:30 +0000687 PyBuffer_Release(&pbuf);
Martin v. Löwisf91d46a2008-08-12 14:49:50 +0000688
Antoine Pitroub26dc462010-05-05 16:27:30 +0000689 if (n < 0) {
690 if (errno == EAGAIN)
691 Py_RETURN_NONE;
692 PyErr_SetFromErrno(PyExc_IOError);
693 return NULL;
694 }
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000695
Antoine Pitroub26dc462010-05-05 16:27:30 +0000696 return PyLong_FromSsize_t(n);
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000697}
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{
Antoine Pitroub26dc462010-05-05 16:27:30 +0000705 Py_off_t pos, res;
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000706
707#ifdef SEEK_SET
Antoine Pitroub26dc462010-05-05 16:27:30 +0000708 /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
709 switch (whence) {
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000710#if SEEK_SET != 0
Antoine Pitroub26dc462010-05-05 16:27:30 +0000711 case 0: whence = SEEK_SET; break;
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000712#endif
713#if SEEK_CUR != 1
Antoine Pitroub26dc462010-05-05 16:27:30 +0000714 case 1: whence = SEEK_CUR; break;
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000715#endif
Benjamin Peterson8024cec2009-01-20 14:31:08 +0000716#if SEEK_END != 2
Antoine Pitroub26dc462010-05-05 16:27:30 +0000717 case 2: whence = SEEK_END; break;
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000718#endif
Antoine Pitroub26dc462010-05-05 16:27:30 +0000719 }
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000720#endif /* SEEK_SET */
721
Antoine Pitroub26dc462010-05-05 16:27:30 +0000722 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)
Antoine Pitroub26dc462010-05-05 16:27:30 +0000730 pos = PyLong_AsLongLong(posobj);
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000731#else
Antoine Pitroub26dc462010-05-05 16:27:30 +0000732 pos = PyLong_AsLong(posobj);
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000733#endif
Antoine Pitroub26dc462010-05-05 16:27:30 +0000734 if (PyErr_Occurred())
735 return NULL;
736 }
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000737
Antoine Pitroub26dc462010-05-05 16:27:30 +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 Pitroub26dc462010-05-05 16:27:30 +0000741 res = _lseeki64(fd, pos, whence);
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000742#else
Antoine Pitroub26dc462010-05-05 16:27:30 +0000743 res = lseek(fd, pos, whence);
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000744#endif
Antoine Pitroub26dc462010-05-05 16:27:30 +0000745 Py_END_ALLOW_THREADS
746 } else
747 res = -1;
748 if (res < 0)
749 return PyErr_SetFromErrno(PyExc_IOError);
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000750
Alexandre Vassalotti1aed6242008-05-09 21:49:43 +0000751#if defined(HAVE_LARGEFILE_SUPPORT)
Antoine Pitroub26dc462010-05-05 16:27:30 +0000752 return PyLong_FromLongLong(res);
Alexandre Vassalotti1aed6242008-05-09 21:49:43 +0000753#else
Antoine Pitroub26dc462010-05-05 16:27:30 +0000754 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{
Antoine Pitroub26dc462010-05-05 16:27:30 +0000761 PyObject *posobj;
762 int whence = 0;
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000763
Antoine Pitroub26dc462010-05-05 16:27:30 +0000764 if (self->fd < 0)
765 return err_closed();
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000766
Antoine Pitroub26dc462010-05-05 16:27:30 +0000767 if (!PyArg_ParseTuple(args, "O|i", &posobj, &whence))
768 return NULL;
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000769
Antoine Pitroub26dc462010-05-05 16:27:30 +0000770 return portable_lseek(self->fd, posobj, whence);
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000771}
772
773static PyObject *
Antoine Pitrou19690592009-06-12 20:14:08 +0000774fileio_tell(fileio *self, PyObject *args)
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000775{
Antoine Pitroub26dc462010-05-05 16:27:30 +0000776 if (self->fd < 0)
777 return err_closed();
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000778
Antoine Pitroub26dc462010-05-05 16:27:30 +0000779 return portable_lseek(self->fd, NULL, 1);
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000780}
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 Pitroub26dc462010-05-05 16:27:30 +0000786 PyObject *posobj = NULL; /* the new size wanted by the user */
Antoine Pitrouf3fa0742010-01-31 22:26:04 +0000787#ifndef MS_WINDOWS
Antoine Pitroub26dc462010-05-05 16:27:30 +0000788 Py_off_t pos;
Antoine Pitrouf3fa0742010-01-31 22:26:04 +0000789#endif
Antoine Pitroub26dc462010-05-05 16:27:30 +0000790 int ret;
791 int fd;
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000792
Antoine Pitroub26dc462010-05-05 16:27:30 +0000793 fd = self->fd;
794 if (fd < 0)
795 return err_closed();
796 if (!self->writable)
797 return err_mode("writing");
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000798
Antoine Pitroub26dc462010-05-05 16:27:30 +0000799 if (!PyArg_ParseTuple(args, "|O", &posobj))
800 return NULL;
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000801
Antoine Pitroub26dc462010-05-05 16:27:30 +0000802 if (posobj == Py_None || posobj == NULL) {
803 /* Get the current position. */
804 posobj = portable_lseek(fd, NULL, 1);
805 if (posobj == NULL)
806 return NULL;
807 }
808 else {
809 Py_INCREF(posobj);
810 }
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000811
812#ifdef MS_WINDOWS
Antoine Pitroub26dc462010-05-05 16:27:30 +0000813 /* MS _chsize doesn't work if newsize doesn't fit in 32 bits,
814 so don't even try using it. */
815 {
816 PyObject *oldposobj, *tempposobj;
817 HANDLE hFile;
Antoine Pitrouf3fa0742010-01-31 22:26:04 +0000818
Antoine Pitroub26dc462010-05-05 16:27:30 +0000819 /* 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 }
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000825
Antoine Pitroub26dc462010-05-05 16:27:30 +0000826 /* 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);
Antoine Pitrouf3fa0742010-01-31 22:26:04 +0000834
Antoine Pitroub26dc462010-05-05 16:27:30 +0000835 /* Truncate. Note that this may grow the file! */
836 Py_BEGIN_ALLOW_THREADS
837 errno = 0;
838 hFile = (HANDLE)_get_osfhandle(fd);
839 ret = hFile == (HANDLE)-1; /* testing for INVALID_HANDLE value */
840 if (ret == 0) {
841 ret = SetEndOfFile(hFile) == 0;
842 if (ret)
843 errno = EACCES;
844 }
845 Py_END_ALLOW_THREADS
846
847 /* we restore the file pointer position in any case */
848 tempposobj = portable_lseek(fd, oldposobj, 0);
849 Py_DECREF(oldposobj);
850 if (tempposobj == NULL) {
851 Py_DECREF(posobj);
852 return NULL;
853 }
854 Py_DECREF(tempposobj);
855 }
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000856#else
Antoine Pitrouf3fa0742010-01-31 22:26:04 +0000857
858#if defined(HAVE_LARGEFILE_SUPPORT)
Antoine Pitroub26dc462010-05-05 16:27:30 +0000859 pos = PyLong_AsLongLong(posobj);
Antoine Pitrouf3fa0742010-01-31 22:26:04 +0000860#else
Antoine Pitroub26dc462010-05-05 16:27:30 +0000861 pos = PyLong_AsLong(posobj);
Antoine Pitrouf3fa0742010-01-31 22:26:04 +0000862#endif
Antoine Pitroub26dc462010-05-05 16:27:30 +0000863 if (PyErr_Occurred()){
864 Py_DECREF(posobj);
865 return NULL;
866 }
Antoine Pitrouf3fa0742010-01-31 22:26:04 +0000867
Antoine Pitroub26dc462010-05-05 16:27:30 +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
Antoine Pitroub26dc462010-05-05 16:27:30 +0000875 if (ret != 0) {
876 Py_DECREF(posobj);
877 PyErr_SetFromErrno(PyExc_IOError);
878 return NULL;
879 }
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000880
Antoine Pitroub26dc462010-05-05 16:27:30 +0000881 return posobj;
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000882}
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{
Antoine Pitroub26dc462010-05-05 16:27:30 +0000888 if (self->readable) {
889 if (self->writable)
890 return "rb+";
891 else
892 return "rb";
893 }
894 else
895 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 Pitroub26dc462010-05-05 16:27:30 +0000901 PyObject *nameobj, *res;
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000902
Antoine Pitroub26dc462010-05-05 16:27:30 +0000903 if (self->fd < 0)
904 return PyString_FromFormat("<_io.FileIO [closed]>");
Antoine Pitrou19690592009-06-12 20:14:08 +0000905
Antoine Pitroub26dc462010-05-05 16:27:30 +0000906 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{
Antoine Pitroub26dc462010-05-05 16:27:30 +0000931 long res;
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000932
Antoine Pitroub26dc462010-05-05 16:27:30 +0000933 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);
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000939}
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"
Antoine Pitroub26dc462010-05-05 16:27:30 +0000946"writing or appending. The file will be created if it doesn't exist\n"
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000947"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,
Antoine Pitroub26dc462010-05-05 16:27:30 +0000988"truncate([size: int]) -> None. Truncate the file to at most size bytes.\n"
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000989"\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,
Antoine Pitroub26dc462010-05-05 16:27:30 +0000995"tell() -> int. Current file position");
Christian Heimes7f39c9f2008-01-25 12:18:43 +0000996
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[] = {
Antoine Pitroub26dc462010-05-05 16:27:30 +00001019 {"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},
Christian Heimes7f39c9f2008-01-25 12:18:43 +00001025#ifdef HAVE_FTRUNCATE
Antoine Pitroub26dc462010-05-05 16:27:30 +00001026 {"truncate", (PyCFunction)fileio_truncate, METH_VARARGS, truncate_doc},
Christian Heimes7f39c9f2008-01-25 12:18:43 +00001027#endif
Antoine Pitroub26dc462010-05-05 16:27:30 +00001028 {"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 */
Christian Heimes7f39c9f2008-01-25 12:18:43 +00001035};
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{
Antoine Pitroub26dc462010-05-05 16:27:30 +00001042 return PyBool_FromLong((long)(self->fd < 0));
Christian Heimes7f39c9f2008-01-25 12:18:43 +00001043}
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{
Antoine Pitroub26dc462010-05-05 16:27:30 +00001048 return PyBool_FromLong((long)(self->closefd));
Amaury Forgeot d'Arc32265652008-11-20 23:34:31 +00001049}
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 Pitroub26dc462010-05-05 16:27:30 +00001054 return PyUnicode_FromString(mode_string(self));
Christian Heimes7f39c9f2008-01-25 12:18:43 +00001055}
1056
1057static PyGetSetDef fileio_getsetlist[] = {
Antoine Pitroub26dc462010-05-05 16:27:30 +00001058 {"closed", (getter)get_closed, NULL, "True if the file is closed"},
1059 {"closefd", (getter)get_closefd, NULL,
1060 "True if the file descriptor will be closed"},
1061 {"mode", (getter)get_mode, NULL, "String giving the file mode"},
1062 {NULL},
Christian Heimes7f39c9f2008-01-25 12:18:43 +00001063};
1064
1065PyTypeObject PyFileIO_Type = {
Antoine Pitroub26dc462010-05-05 16:27:30 +00001066 PyVarObject_HEAD_INIT(NULL, 0)
1067 "_io.FileIO",
1068 sizeof(fileio),
1069 0,
1070 (destructor)fileio_dealloc, /* tp_dealloc */
1071 0, /* tp_print */
1072 0, /* tp_getattr */
1073 0, /* tp_setattr */
1074 0, /* tp_reserved */
1075 (reprfunc)fileio_repr, /* tp_repr */
1076 0, /* tp_as_number */
1077 0, /* tp_as_sequence */
1078 0, /* tp_as_mapping */
1079 0, /* tp_hash */
1080 0, /* tp_call */
1081 0, /* tp_str */
1082 PyObject_GenericGetAttr, /* tp_getattro */
1083 0, /* tp_setattro */
1084 0, /* tp_as_buffer */
1085 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
1086 | Py_TPFLAGS_HAVE_GC, /* tp_flags */
1087 fileio_doc, /* tp_doc */
1088 (traverseproc)fileio_traverse, /* tp_traverse */
1089 (inquiry)fileio_clear, /* tp_clear */
1090 0, /* tp_richcompare */
1091 offsetof(fileio, weakreflist), /* tp_weaklistoffset */
1092 0, /* tp_iter */
1093 0, /* tp_iternext */
1094 fileio_methods, /* tp_methods */
1095 0, /* tp_members */
1096 fileio_getsetlist, /* tp_getset */
1097 0, /* tp_base */
1098 0, /* tp_dict */
1099 0, /* tp_descr_get */
1100 0, /* tp_descr_set */
1101 offsetof(fileio, dict), /* tp_dictoffset */
1102 fileio_init, /* tp_init */
1103 PyType_GenericAlloc, /* tp_alloc */
1104 fileio_new, /* tp_new */
1105 PyObject_GC_Del, /* tp_free */
Christian Heimes7f39c9f2008-01-25 12:18:43 +00001106};