blob: 57cd9aabe2ac562de4fdf5e6767d3e5ebef054e0 [file] [log] [blame]
Guido van Rossuma9e20242007-03-08 00:43:48 +00001/* Author: Daniel Stutzbach */
2
3#define PY_SSIZE_T_CLEAN
4#include "Python.h"
Antoine Pitroue033e062010-10-29 10:38:18 +00005#include "structmember.h"
Benjamin Peterson2614cda2010-03-21 22:36:19 +00006#ifdef HAVE_SYS_TYPES_H
Guido van Rossuma9e20242007-03-08 00:43:48 +00007#include <sys/types.h>
Benjamin Peterson2614cda2010-03-21 22:36:19 +00008#endif
9#ifdef HAVE_SYS_STAT_H
Guido van Rossuma9e20242007-03-08 00:43:48 +000010#include <sys/stat.h>
Benjamin Peterson2614cda2010-03-21 22:36:19 +000011#endif
12#ifdef HAVE_FCNTL_H
Guido van Rossuma9e20242007-03-08 00:43:48 +000013#include <fcntl.h>
Benjamin Peterson2614cda2010-03-21 22:36:19 +000014#endif
Guido van Rossuma9e20242007-03-08 00:43:48 +000015#include <stddef.h> /* For offsetof */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000016#include "_iomodule.h"
Guido van Rossuma9e20242007-03-08 00:43:48 +000017
18/*
19 * Known likely problems:
20 *
21 * - Files larger then 2**32-1
22 * - Files with unicode filenames
23 * - Passing numbers greater than 2**32-1 when an integer is expected
24 * - Making it work on Windows and other oddball platforms
25 *
26 * To Do:
27 *
28 * - autoconfify header file inclusion
Guido van Rossuma9e20242007-03-08 00:43:48 +000029 */
30
31#ifdef MS_WINDOWS
32/* can simulate truncate with Win32 API functions; see file_truncate */
Thomas Hellerfdeee3a2007-07-12 11:21:36 +000033#define HAVE_FTRUNCATE
Guido van Rossuma9e20242007-03-08 00:43:48 +000034#define WIN32_LEAN_AND_MEAN
35#include <windows.h>
36#endif
37
Christian Heimesa872de52008-12-05 08:26:55 +000038#if BUFSIZ < (8*1024)
39#define SMALLCHUNK (8*1024)
40#elif (BUFSIZ >= (2 << 25))
41#error "unreasonable BUFSIZ > 64MB defined"
42#else
43#define SMALLCHUNK BUFSIZ
44#endif
45
Guido van Rossuma9e20242007-03-08 00:43:48 +000046typedef struct {
Antoine Pitrouae4b4722010-05-05 16:31:07 +000047 PyObject_HEAD
48 int fd;
Charles-François Natalidc3044c2012-01-09 22:40:02 +010049 unsigned int created : 1;
Antoine Pitrouae4b4722010-05-05 16:31:07 +000050 unsigned int readable : 1;
51 unsigned int writable : 1;
52 signed int seekable : 2; /* -1 means unknown */
53 unsigned int closefd : 1;
Antoine Pitroue033e062010-10-29 10:38:18 +000054 unsigned int deallocating: 1;
Antoine Pitrouae4b4722010-05-05 16:31:07 +000055 PyObject *weakreflist;
56 PyObject *dict;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +000057} fileio;
Guido van Rossuma9e20242007-03-08 00:43:48 +000058
Collin Winteraf334382007-03-08 21:46:15 +000059PyTypeObject PyFileIO_Type;
60
Guido van Rossuma9e20242007-03-08 00:43:48 +000061#define PyFileIO_Check(op) (PyObject_TypeCheck((op), &PyFileIO_Type))
62
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000063int
64_PyFileIO_closed(PyObject *self)
65{
Antoine Pitrouae4b4722010-05-05 16:31:07 +000066 return ((fileio *)self)->fd < 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000067}
Antoine Pitrou08838b62009-01-21 00:55:13 +000068
Antoine Pitroue033e062010-10-29 10:38:18 +000069/* Because this can call arbitrary code, it shouldn't be called when
70 the refcount is 0 (that is, not directly from tp_dealloc unless
71 the refcount has been temporarily re-incremented). */
72static PyObject *
73fileio_dealloc_warn(fileio *self, PyObject *source)
74{
75 if (self->fd >= 0 && self->closefd) {
76 PyObject *exc, *val, *tb;
77 PyErr_Fetch(&exc, &val, &tb);
78 if (PyErr_WarnFormat(PyExc_ResourceWarning, 1,
79 "unclosed file %R", source)) {
80 /* Spurious errors can appear at shutdown */
81 if (PyErr_ExceptionMatches(PyExc_Warning))
82 PyErr_WriteUnraisable((PyObject *) self);
83 }
84 PyErr_Restore(exc, val, tb);
85 }
86 Py_RETURN_NONE;
87}
88
Antoine Pitrou7fb111b2009-03-04 11:14:01 +000089static PyObject *
90portable_lseek(int fd, PyObject *posobj, int whence);
91
Antoine Pitroua28fcfd2009-03-13 23:42:55 +000092static PyObject *portable_lseek(int fd, PyObject *posobj, int whence);
93
Kristján Valur Jónsson19288c22008-12-18 17:15:54 +000094/* Returns 0 on success, -1 with exception set on failure. */
Neal Norwitz88b44da2007-08-12 17:23:54 +000095static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +000096internal_close(fileio *self)
Guido van Rossuma9e20242007-03-08 00:43:48 +000097{
Antoine Pitrouae4b4722010-05-05 16:31:07 +000098 int err = 0;
99 int save_errno = 0;
100 if (self->fd >= 0) {
101 int fd = self->fd;
102 self->fd = -1;
103 /* fd is accessible and someone else may have closed it */
104 if (_PyVerify_fd(fd)) {
105 Py_BEGIN_ALLOW_THREADS
106 err = close(fd);
107 if (err < 0)
108 save_errno = errno;
109 Py_END_ALLOW_THREADS
110 } else {
111 save_errno = errno;
112 err = -1;
113 }
114 }
115 if (err < 0) {
116 errno = save_errno;
117 PyErr_SetFromErrno(PyExc_IOError);
118 return -1;
119 }
120 return 0;
Neal Norwitz88b44da2007-08-12 17:23:54 +0000121}
122
123static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000124fileio_close(fileio *self)
Neal Norwitz88b44da2007-08-12 17:23:54 +0000125{
Martin v. Löwisbd928fe2011-10-14 10:20:37 +0200126 _Py_IDENTIFIER(close);
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000127 if (!self->closefd) {
128 self->fd = -1;
129 Py_RETURN_NONE;
130 }
Antoine Pitroue033e062010-10-29 10:38:18 +0000131 if (self->deallocating) {
132 PyObject *r = fileio_dealloc_warn(self, (PyObject *) self);
133 if (r)
134 Py_DECREF(r);
135 else
136 PyErr_Clear();
137 }
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000138 errno = internal_close(self);
139 if (errno < 0)
140 return NULL;
Guido van Rossuma9e20242007-03-08 00:43:48 +0000141
Martin v. Löwisafe55bb2011-10-09 10:38:36 +0200142 return _PyObject_CallMethodId((PyObject*)&PyRawIOBase_Type,
143 &PyId_close, "O", self);
Guido van Rossuma9e20242007-03-08 00:43:48 +0000144}
145
146static PyObject *
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000147fileio_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
Guido van Rossuma9e20242007-03-08 00:43:48 +0000148{
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000149 fileio *self;
Guido van Rossuma9e20242007-03-08 00:43:48 +0000150
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000151 assert(type != NULL && type->tp_alloc != NULL);
Guido van Rossuma9e20242007-03-08 00:43:48 +0000152
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000153 self = (fileio *) type->tp_alloc(type, 0);
154 if (self != NULL) {
155 self->fd = -1;
Charles-François Natalidc3044c2012-01-09 22:40:02 +0100156 self->created = 0;
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000157 self->readable = 0;
158 self->writable = 0;
159 self->seekable = -1;
160 self->closefd = 1;
161 self->weakreflist = NULL;
162 }
Guido van Rossuma9e20242007-03-08 00:43:48 +0000163
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000164 return (PyObject *) self;
Guido van Rossuma9e20242007-03-08 00:43:48 +0000165}
166
167/* On Unix, open will succeed for directories.
168 In Python, there should be no file objects referring to
169 directories, so we need a check. */
170
171static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000172dircheck(fileio* self, const char *name)
Guido van Rossuma9e20242007-03-08 00:43:48 +0000173{
174#if defined(HAVE_FSTAT) && defined(S_IFDIR) && defined(EISDIR)
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000175 struct stat buf;
176 if (self->fd < 0)
177 return 0;
178 if (fstat(self->fd, &buf) == 0 && S_ISDIR(buf.st_mode)) {
179 char *msg = strerror(EISDIR);
180 PyObject *exc;
181 if (internal_close(self))
182 return -1;
Guido van Rossum53807da2007-04-10 19:01:47 +0000183
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000184 exc = PyObject_CallFunction(PyExc_IOError, "(iss)",
185 EISDIR, msg, name);
186 PyErr_SetObject(PyExc_IOError, exc);
187 Py_XDECREF(exc);
188 return -1;
189 }
Guido van Rossuma9e20242007-03-08 00:43:48 +0000190#endif
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000191 return 0;
Guido van Rossuma9e20242007-03-08 00:43:48 +0000192}
193
Benjamin Peterson806d4022009-01-19 15:11:51 +0000194static int
195check_fd(int fd)
196{
197#if defined(HAVE_FSTAT)
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000198 struct stat buf;
199 if (!_PyVerify_fd(fd) || (fstat(fd, &buf) < 0 && errno == EBADF)) {
200 PyObject *exc;
201 char *msg = strerror(EBADF);
202 exc = PyObject_CallFunction(PyExc_OSError, "(is)",
203 EBADF, msg);
204 PyErr_SetObject(PyExc_OSError, exc);
205 Py_XDECREF(exc);
206 return -1;
207 }
Benjamin Peterson806d4022009-01-19 15:11:51 +0000208#endif
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000209 return 0;
Benjamin Peterson806d4022009-01-19 15:11:51 +0000210}
211
Guido van Rossuma9e20242007-03-08 00:43:48 +0000212
213static int
214fileio_init(PyObject *oself, PyObject *args, PyObject *kwds)
215{
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000216 fileio *self = (fileio *) oself;
Ross Lagerwall59142db2011-10-31 20:34:46 +0200217 static char *kwlist[] = {"file", "mode", "closefd", "opener", NULL};
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000218 const char *name = NULL;
Ross Lagerwall59142db2011-10-31 20:34:46 +0200219 PyObject *nameobj, *stringobj = NULL, *opener = Py_None;
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000220 char *mode = "r";
221 char *s;
Thomas Helleraf2be262007-07-12 11:03:13 +0000222#ifdef MS_WINDOWS
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000223 Py_UNICODE *widename = NULL;
Thomas Helleraf2be262007-07-12 11:03:13 +0000224#endif
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000225 int ret = 0;
226 int rwa = 0, plus = 0, append = 0;
227 int flags = 0;
228 int fd = -1;
229 int closefd = 1;
Guido van Rossuma9e20242007-03-08 00:43:48 +0000230
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000231 assert(PyFileIO_Check(oself));
232 if (self->fd >= 0) {
233 /* Have to close the existing file first. */
234 if (internal_close(self) < 0)
235 return -1;
236 }
Guido van Rossuma9e20242007-03-08 00:43:48 +0000237
Ross Lagerwall59142db2011-10-31 20:34:46 +0200238 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|siO:fileio",
239 kwlist, &nameobj, &mode, &closefd,
240 &opener))
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000241 return -1;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000242
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000243 if (PyFloat_Check(nameobj)) {
244 PyErr_SetString(PyExc_TypeError,
245 "integer argument expected, got float");
246 return -1;
247 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000248
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000249 fd = PyLong_AsLong(nameobj);
250 if (fd < 0) {
251 if (!PyErr_Occurred()) {
252 PyErr_SetString(PyExc_ValueError,
253 "Negative filedescriptor");
254 return -1;
255 }
256 PyErr_Clear();
257 }
Guido van Rossumb0428152007-04-08 17:44:42 +0000258
Hirokazu Yamamoto8223c242009-05-17 04:21:53 +0000259#ifdef MS_WINDOWS
Victor Stinnerfe9a8612011-09-29 23:19:04 +0200260 if (PyUnicode_Check(nameobj)) {
261 widename = PyUnicode_AsUnicode(nameobj);
262 if (widename == NULL)
263 return -1;
264 } else
Guido van Rossuma9e20242007-03-08 00:43:48 +0000265#endif
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000266 if (fd < 0)
267 {
268 if (PyBytes_Check(nameobj) || PyByteArray_Check(nameobj)) {
269 Py_ssize_t namelen;
270 if (PyObject_AsCharBuffer(nameobj, &name, &namelen) < 0)
271 return -1;
272 }
273 else {
274 PyObject *u = PyUnicode_FromObject(nameobj);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000275
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000276 if (u == NULL)
277 return -1;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000278
Victor Stinnerae6265f2010-05-15 16:27:27 +0000279 stringobj = PyUnicode_EncodeFSDefault(u);
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000280 Py_DECREF(u);
281 if (stringobj == NULL)
282 return -1;
283 if (!PyBytes_Check(stringobj)) {
284 PyErr_SetString(PyExc_TypeError,
285 "encoder failed to return bytes");
286 goto error;
287 }
288 name = PyBytes_AS_STRING(stringobj);
289 }
290 }
Guido van Rossuma9e20242007-03-08 00:43:48 +0000291
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000292 s = mode;
293 while (*s) {
294 switch (*s++) {
Charles-François Natalidc3044c2012-01-09 22:40:02 +0100295 case 'x':
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000296 if (rwa) {
297 bad_mode:
298 PyErr_SetString(PyExc_ValueError,
Charles-François Natalidc3044c2012-01-09 22:40:02 +0100299 "Must have exactly one of create/read/write/append "
Georg Brandl28928ae2010-10-21 13:45:52 +0000300 "mode and at most one plus");
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000301 goto error;
302 }
303 rwa = 1;
Charles-François Natalidc3044c2012-01-09 22:40:02 +0100304 self->created = 1;
305 self->writable = 1;
306 flags |= O_EXCL | O_CREAT;
307 break;
308 case 'r':
309 if (rwa)
310 goto bad_mode;
311 rwa = 1;
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000312 self->readable = 1;
313 break;
314 case 'w':
315 if (rwa)
316 goto bad_mode;
317 rwa = 1;
318 self->writable = 1;
319 flags |= O_CREAT | O_TRUNC;
320 break;
321 case 'a':
322 if (rwa)
323 goto bad_mode;
324 rwa = 1;
325 self->writable = 1;
326 flags |= O_CREAT;
327 append = 1;
328 break;
329 case 'b':
330 break;
331 case '+':
332 if (plus)
333 goto bad_mode;
334 self->readable = self->writable = 1;
335 plus = 1;
336 break;
337 default:
338 PyErr_Format(PyExc_ValueError,
339 "invalid mode: %.200s", mode);
340 goto error;
341 }
342 }
Guido van Rossuma9e20242007-03-08 00:43:48 +0000343
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000344 if (!rwa)
345 goto bad_mode;
Guido van Rossuma9e20242007-03-08 00:43:48 +0000346
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000347 if (self->readable && self->writable)
348 flags |= O_RDWR;
349 else if (self->readable)
350 flags |= O_RDONLY;
351 else
352 flags |= O_WRONLY;
Guido van Rossuma9e20242007-03-08 00:43:48 +0000353
354#ifdef O_BINARY
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000355 flags |= O_BINARY;
Guido van Rossuma9e20242007-03-08 00:43:48 +0000356#endif
357
Walter Dörwald0e411482007-06-06 16:55:38 +0000358#ifdef O_APPEND
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000359 if (append)
360 flags |= O_APPEND;
Walter Dörwald0e411482007-06-06 16:55:38 +0000361#endif
362
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000363 if (fd >= 0) {
364 if (check_fd(fd))
365 goto error;
366 self->fd = fd;
367 self->closefd = closefd;
368 }
369 else {
370 self->closefd = 1;
371 if (!closefd) {
372 PyErr_SetString(PyExc_ValueError,
373 "Cannot use closefd=False with file name");
374 goto error;
375 }
Guido van Rossum2dced8b2007-10-30 17:27:30 +0000376
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000377 errno = 0;
Ross Lagerwall59142db2011-10-31 20:34:46 +0200378 if (opener == Py_None) {
379 Py_BEGIN_ALLOW_THREADS
Thomas Helleraf2be262007-07-12 11:03:13 +0000380#ifdef MS_WINDOWS
Ross Lagerwall59142db2011-10-31 20:34:46 +0200381 if (widename != NULL)
382 self->fd = _wopen(widename, flags, 0666);
383 else
Thomas Helleraf2be262007-07-12 11:03:13 +0000384#endif
Ross Lagerwall59142db2011-10-31 20:34:46 +0200385 self->fd = open(name, flags, 0666);
386 Py_END_ALLOW_THREADS
387 } else {
388 PyObject *fdobj = PyObject_CallFunction(
389 opener, "Oi", nameobj, flags);
390 if (fdobj == NULL)
391 goto error;
392 if (!PyLong_Check(fdobj)) {
393 Py_DECREF(fdobj);
394 PyErr_SetString(PyExc_TypeError,
395 "expected integer from opener");
396 goto error;
397 }
398
399 self->fd = PyLong_AsLong(fdobj);
400 Py_DECREF(fdobj);
401 if (self->fd == -1) {
402 goto error;
403 }
404 }
405
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000406 if (self->fd < 0) {
Christian Heimes0b489542007-10-31 19:20:48 +0000407#ifdef MS_WINDOWS
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000408 if (widename != NULL)
Victor Stinnerfe9a8612011-09-29 23:19:04 +0200409 PyErr_SetFromErrnoWithFilenameObject(PyExc_IOError, nameobj);
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000410 else
Christian Heimes0b489542007-10-31 19:20:48 +0000411#endif
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000412 PyErr_SetFromErrnoWithFilename(PyExc_IOError, name);
413 goto error;
414 }
Benjamin Peterson430d4692010-10-30 23:13:57 +0000415 if (dircheck(self, name) < 0)
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000416 goto error;
417 }
Guido van Rossuma9e20242007-03-08 00:43:48 +0000418
Victor Stinner89e34362011-01-07 18:47:22 +0000419#if defined(MS_WINDOWS) || defined(__CYGWIN__)
420 /* don't translate newlines (\r\n <=> \n) */
421 _setmode(self->fd, O_BINARY);
422#endif
423
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000424 if (PyObject_SetAttrString((PyObject *)self, "name", nameobj) < 0)
425 goto error;
Antoine Pitrou08838b62009-01-21 00:55:13 +0000426
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000427 if (append) {
428 /* For consistent behaviour, we explicitly seek to the
429 end of file (otherwise, it might be done only on the
430 first write()). */
431 PyObject *pos = portable_lseek(self->fd, NULL, 2);
Antoine Pitrou8d2b51b2010-10-30 16:19:14 +0000432 if (pos == NULL) {
433 if (closefd) {
434 close(self->fd);
435 self->fd = -1;
436 }
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000437 goto error;
Antoine Pitrou8d2b51b2010-10-30 16:19:14 +0000438 }
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000439 Py_DECREF(pos);
440 }
Antoine Pitrou7fb111b2009-03-04 11:14:01 +0000441
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000442 goto done;
Guido van Rossuma9e20242007-03-08 00:43:48 +0000443
444 error:
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000445 ret = -1;
Benjamin Petersonbbb04122010-10-30 23:16:28 +0000446 if (self->fd >= 0)
447 internal_close(self);
Guido van Rossum53807da2007-04-10 19:01:47 +0000448
Guido van Rossuma9e20242007-03-08 00:43:48 +0000449 done:
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000450 Py_CLEAR(stringobj);
451 return ret;
Guido van Rossuma9e20242007-03-08 00:43:48 +0000452}
453
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000454static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000455fileio_traverse(fileio *self, visitproc visit, void *arg)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000456{
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000457 Py_VISIT(self->dict);
458 return 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000459}
460
461static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000462fileio_clear(fileio *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000463{
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000464 Py_CLEAR(self->dict);
465 return 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000466}
467
Guido van Rossuma9e20242007-03-08 00:43:48 +0000468static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000469fileio_dealloc(fileio *self)
Guido van Rossuma9e20242007-03-08 00:43:48 +0000470{
Antoine Pitroue033e062010-10-29 10:38:18 +0000471 self->deallocating = 1;
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000472 if (_PyIOBase_finalize((PyObject *) self) < 0)
473 return;
474 _PyObject_GC_UNTRACK(self);
475 if (self->weakreflist != NULL)
476 PyObject_ClearWeakRefs((PyObject *) self);
477 Py_CLEAR(self->dict);
478 Py_TYPE(self)->tp_free((PyObject *)self);
Guido van Rossuma9e20242007-03-08 00:43:48 +0000479}
480
481static PyObject *
482err_closed(void)
483{
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000484 PyErr_SetString(PyExc_ValueError, "I/O operation on closed file");
485 return NULL;
Guido van Rossuma9e20242007-03-08 00:43:48 +0000486}
487
488static PyObject *
Guido van Rossum53807da2007-04-10 19:01:47 +0000489err_mode(char *action)
490{
Antoine Pitrou0d739d72010-09-05 23:01:12 +0000491 PyErr_Format(IO_STATE->unsupported_operation,
492 "File not open for %s", action);
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000493 return NULL;
Guido van Rossum53807da2007-04-10 19:01:47 +0000494}
495
496static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000497fileio_fileno(fileio *self)
Guido van Rossuma9e20242007-03-08 00:43:48 +0000498{
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000499 if (self->fd < 0)
500 return err_closed();
501 return PyLong_FromLong((long) self->fd);
Guido van Rossuma9e20242007-03-08 00:43:48 +0000502}
503
504static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000505fileio_readable(fileio *self)
Guido van Rossuma9e20242007-03-08 00:43:48 +0000506{
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000507 if (self->fd < 0)
508 return err_closed();
509 return PyBool_FromLong((long) self->readable);
Guido van Rossuma9e20242007-03-08 00:43:48 +0000510}
511
512static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000513fileio_writable(fileio *self)
Guido van Rossuma9e20242007-03-08 00:43:48 +0000514{
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000515 if (self->fd < 0)
516 return err_closed();
517 return PyBool_FromLong((long) self->writable);
Guido van Rossuma9e20242007-03-08 00:43:48 +0000518}
519
520static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000521fileio_seekable(fileio *self)
Guido van Rossuma9e20242007-03-08 00:43:48 +0000522{
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000523 if (self->fd < 0)
524 return err_closed();
525 if (self->seekable < 0) {
526 PyObject *pos = portable_lseek(self->fd, NULL, SEEK_CUR);
527 if (pos == NULL) {
528 PyErr_Clear();
529 self->seekable = 0;
530 } else {
531 Py_DECREF(pos);
532 self->seekable = 1;
533 }
534 }
535 return PyBool_FromLong((long) self->seekable);
Guido van Rossuma9e20242007-03-08 00:43:48 +0000536}
537
538static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000539fileio_readinto(fileio *self, PyObject *args)
Guido van Rossuma9e20242007-03-08 00:43:48 +0000540{
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000541 Py_buffer pbuf;
Victor Stinnere6edec22011-01-04 00:29:35 +0000542 Py_ssize_t n, len;
Antoine Pitrouc345ce12011-12-16 12:28:32 +0100543 int err;
Guido van Rossum53807da2007-04-10 19:01:47 +0000544
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000545 if (self->fd < 0)
546 return err_closed();
547 if (!self->readable)
548 return err_mode("reading");
Guido van Rossum53807da2007-04-10 19:01:47 +0000549
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000550 if (!PyArg_ParseTuple(args, "w*", &pbuf))
551 return NULL;
Guido van Rossuma9e20242007-03-08 00:43:48 +0000552
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000553 if (_PyVerify_fd(self->fd)) {
Victor Stinnere6edec22011-01-04 00:29:35 +0000554 len = pbuf.len;
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000555 Py_BEGIN_ALLOW_THREADS
556 errno = 0;
Victor Stinnere6edec22011-01-04 00:29:35 +0000557#if defined(MS_WIN64) || defined(MS_WINDOWS)
558 if (len > INT_MAX)
559 len = INT_MAX;
560 n = read(self->fd, pbuf.buf, (int)len);
561#else
Victor Stinner72344792011-01-11 00:04:12 +0000562 n = read(self->fd, pbuf.buf, len);
Victor Stinnere6edec22011-01-04 00:29:35 +0000563#endif
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000564 Py_END_ALLOW_THREADS
565 } else
566 n = -1;
Antoine Pitrouc345ce12011-12-16 12:28:32 +0100567 err = errno;
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000568 PyBuffer_Release(&pbuf);
569 if (n < 0) {
Antoine Pitrouc345ce12011-12-16 12:28:32 +0100570 if (err == EAGAIN)
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000571 Py_RETURN_NONE;
Antoine Pitrouc345ce12011-12-16 12:28:32 +0100572 errno = err;
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000573 PyErr_SetFromErrno(PyExc_IOError);
574 return NULL;
575 }
Guido van Rossuma9e20242007-03-08 00:43:48 +0000576
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000577 return PyLong_FromSsize_t(n);
Guido van Rossuma9e20242007-03-08 00:43:48 +0000578}
579
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000580static size_t
Victor Stinnere9d44ccb2011-05-26 00:16:44 +0200581new_buffersize(fileio *self, size_t currentsize
582#ifdef HAVE_FSTAT
Victor Stinnera2a64772011-10-11 22:45:02 +0200583 , Py_off_t pos, Py_off_t end
Victor Stinnere9d44ccb2011-05-26 00:16:44 +0200584#endif
585 )
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000586{
587#ifdef HAVE_FSTAT
Victor Stinnera2a64772011-10-11 22:45:02 +0200588 if (end != (Py_off_t)-1) {
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000589 /* Files claiming a size smaller than SMALLCHUNK may
590 actually be streaming pseudo-files. In this case, we
591 apply the more aggressive algorithm below.
592 */
593 if (end >= SMALLCHUNK && end >= pos && pos >= 0) {
594 /* Add 1 so if the file were to grow we'd notice. */
Victor Stinnerc5af7732011-10-11 23:00:31 +0200595 Py_off_t bufsize = currentsize + end - pos + 1;
596 if (bufsize < PY_SSIZE_T_MAX)
597 return (size_t)bufsize;
598 else
599 return PY_SSIZE_T_MAX;
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000600 }
601 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000602#endif
Nadeem Vawdad41a98b2011-10-13 13:34:16 +0200603 /* Expand the buffer by an amount proportional to the current size,
604 giving us amortized linear-time behavior. Use a less-than-double
605 growth factor to avoid excessive allocation. */
606 return currentsize + (currentsize >> 3) + 6;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000607}
608
Guido van Rossum7165cb12007-07-10 06:54:34 +0000609static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000610fileio_readall(fileio *self)
Guido van Rossum7165cb12007-07-10 06:54:34 +0000611{
Victor Stinnere9d44ccb2011-05-26 00:16:44 +0200612#ifdef HAVE_FSTAT
613 struct stat st;
Victor Stinnera2a64772011-10-11 22:45:02 +0200614 Py_off_t pos, end;
Victor Stinnere9d44ccb2011-05-26 00:16:44 +0200615#endif
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000616 PyObject *result;
617 Py_ssize_t total = 0;
618 int n;
Victor Stinnere9d44ccb2011-05-26 00:16:44 +0200619 size_t newsize;
Guido van Rossum7165cb12007-07-10 06:54:34 +0000620
Victor Stinnerb79f28c2011-05-25 22:09:03 +0200621 if (self->fd < 0)
622 return err_closed();
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000623 if (!_PyVerify_fd(self->fd))
624 return PyErr_SetFromErrno(PyExc_IOError);
Kristján Valur Jónssona8abe862009-03-24 15:27:42 +0000625
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000626 result = PyBytes_FromStringAndSize(NULL, SMALLCHUNK);
627 if (result == NULL)
628 return NULL;
Guido van Rossum7165cb12007-07-10 06:54:34 +0000629
Victor Stinnere9d44ccb2011-05-26 00:16:44 +0200630#ifdef HAVE_FSTAT
631#if defined(MS_WIN64) || defined(MS_WINDOWS)
632 pos = _lseeki64(self->fd, 0L, SEEK_CUR);
633#else
634 pos = lseek(self->fd, 0L, SEEK_CUR);
635#endif
636 if (fstat(self->fd, &st) == 0)
637 end = st.st_size;
638 else
Victor Stinnera2a64772011-10-11 22:45:02 +0200639 end = (Py_off_t)-1;
Victor Stinnere9d44ccb2011-05-26 00:16:44 +0200640#endif
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000641 while (1) {
Victor Stinnere9d44ccb2011-05-26 00:16:44 +0200642#ifdef HAVE_FSTAT
643 newsize = new_buffersize(self, total, pos, end);
644#else
645 newsize = new_buffersize(self, total);
646#endif
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000647 if (newsize > PY_SSIZE_T_MAX || newsize <= 0) {
648 PyErr_SetString(PyExc_OverflowError,
649 "unbounded read returned more bytes "
650 "than a Python string can hold ");
651 Py_DECREF(result);
652 return NULL;
653 }
Christian Heimesa872de52008-12-05 08:26:55 +0000654
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000655 if (PyBytes_GET_SIZE(result) < (Py_ssize_t)newsize) {
656 if (_PyBytes_Resize(&result, newsize) < 0) {
657 if (total == 0) {
658 Py_DECREF(result);
659 return NULL;
660 }
661 PyErr_Clear();
662 break;
663 }
664 }
665 Py_BEGIN_ALLOW_THREADS
666 errno = 0;
667 n = read(self->fd,
668 PyBytes_AS_STRING(result) + total,
669 newsize - total);
670 Py_END_ALLOW_THREADS
671 if (n == 0)
672 break;
673 if (n < 0) {
674 if (total > 0)
675 break;
676 if (errno == EAGAIN) {
677 Py_DECREF(result);
678 Py_RETURN_NONE;
679 }
680 Py_DECREF(result);
681 PyErr_SetFromErrno(PyExc_IOError);
682 return NULL;
683 }
684 total += n;
Victor Stinnere9d44ccb2011-05-26 00:16:44 +0200685#ifdef HAVE_FSTAT
686 pos += n;
687#endif
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000688 }
Guido van Rossum7165cb12007-07-10 06:54:34 +0000689
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000690 if (PyBytes_GET_SIZE(result) > total) {
691 if (_PyBytes_Resize(&result, total) < 0) {
692 /* This should never happen, but just in case */
693 Py_DECREF(result);
694 return NULL;
695 }
696 }
697 return result;
Guido van Rossum7165cb12007-07-10 06:54:34 +0000698}
699
Guido van Rossuma9e20242007-03-08 00:43:48 +0000700static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000701fileio_read(fileio *self, PyObject *args)
Guido van Rossuma9e20242007-03-08 00:43:48 +0000702{
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000703 char *ptr;
704 Py_ssize_t n;
705 Py_ssize_t size = -1;
706 PyObject *bytes;
Guido van Rossuma9e20242007-03-08 00:43:48 +0000707
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000708 if (self->fd < 0)
709 return err_closed();
710 if (!self->readable)
711 return err_mode("reading");
Guido van Rossuma9e20242007-03-08 00:43:48 +0000712
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000713 if (!PyArg_ParseTuple(args, "|O&", &_PyIO_ConvertSsize_t, &size))
714 return NULL;
Guido van Rossuma9e20242007-03-08 00:43:48 +0000715
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000716 if (size < 0) {
717 return fileio_readall(self);
718 }
Guido van Rossumc2f93dc2007-05-24 00:50:02 +0000719
Victor Stinnerc655a722011-07-05 11:31:49 +0200720#if defined(MS_WIN64) || defined(MS_WINDOWS)
721 if (size > INT_MAX)
722 size = INT_MAX;
723#endif
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000724 bytes = PyBytes_FromStringAndSize(NULL, size);
725 if (bytes == NULL)
726 return NULL;
727 ptr = PyBytes_AS_STRING(bytes);
Guido van Rossuma9e20242007-03-08 00:43:48 +0000728
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000729 if (_PyVerify_fd(self->fd)) {
730 Py_BEGIN_ALLOW_THREADS
731 errno = 0;
Victor Stinnerc655a722011-07-05 11:31:49 +0200732#if defined(MS_WIN64) || defined(MS_WINDOWS)
733 n = read(self->fd, ptr, (int)size);
734#else
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000735 n = read(self->fd, ptr, size);
Victor Stinnerc655a722011-07-05 11:31:49 +0200736#endif
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000737 Py_END_ALLOW_THREADS
738 } else
739 n = -1;
Guido van Rossuma9e20242007-03-08 00:43:48 +0000740
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000741 if (n < 0) {
Antoine Pitrouc345ce12011-12-16 12:28:32 +0100742 int err = errno;
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000743 Py_DECREF(bytes);
Antoine Pitrouc345ce12011-12-16 12:28:32 +0100744 if (err == EAGAIN)
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000745 Py_RETURN_NONE;
Antoine Pitrouc345ce12011-12-16 12:28:32 +0100746 errno = err;
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000747 PyErr_SetFromErrno(PyExc_IOError);
748 return NULL;
749 }
Guido van Rossuma9e20242007-03-08 00:43:48 +0000750
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000751 if (n != size) {
752 if (_PyBytes_Resize(&bytes, n) < 0) {
753 Py_DECREF(bytes);
754 return NULL;
755 }
756 }
Guido van Rossuma9e20242007-03-08 00:43:48 +0000757
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000758 return (PyObject *) bytes;
Guido van Rossuma9e20242007-03-08 00:43:48 +0000759}
760
761static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000762fileio_write(fileio *self, PyObject *args)
Guido van Rossuma9e20242007-03-08 00:43:48 +0000763{
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000764 Py_buffer pbuf;
Victor Stinnere6edec22011-01-04 00:29:35 +0000765 Py_ssize_t n, len;
Antoine Pitrouc345ce12011-12-16 12:28:32 +0100766 int err;
Guido van Rossuma9e20242007-03-08 00:43:48 +0000767
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000768 if (self->fd < 0)
769 return err_closed();
770 if (!self->writable)
771 return err_mode("writing");
Guido van Rossum53807da2007-04-10 19:01:47 +0000772
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000773 if (!PyArg_ParseTuple(args, "y*", &pbuf))
774 return NULL;
Guido van Rossuma9e20242007-03-08 00:43:48 +0000775
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000776 if (_PyVerify_fd(self->fd)) {
777 Py_BEGIN_ALLOW_THREADS
778 errno = 0;
Victor Stinnere6edec22011-01-04 00:29:35 +0000779 len = pbuf.len;
780#if defined(MS_WIN64) || defined(MS_WINDOWS)
Victor Stinnere0daff12011-03-20 23:36:35 +0100781 if (len > 32767 && isatty(self->fd)) {
782 /* Issue #11395: the Windows console returns an error (12: not
783 enough space error) on writing into stdout if stdout mode is
784 binary and the length is greater than 66,000 bytes (or less,
785 depending on heap usage). */
786 len = 32767;
787 }
788 else if (len > INT_MAX)
Victor Stinnere6edec22011-01-04 00:29:35 +0000789 len = INT_MAX;
790 n = write(self->fd, pbuf.buf, (int)len);
791#else
Victor Stinner72344792011-01-11 00:04:12 +0000792 n = write(self->fd, pbuf.buf, len);
Victor Stinnere6edec22011-01-04 00:29:35 +0000793#endif
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000794 Py_END_ALLOW_THREADS
795 } else
796 n = -1;
Antoine Pitrouc345ce12011-12-16 12:28:32 +0100797 err = errno;
Guido van Rossuma9e20242007-03-08 00:43:48 +0000798
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000799 PyBuffer_Release(&pbuf);
Martin v. Löwis423be952008-08-13 15:53:07 +0000800
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000801 if (n < 0) {
Antoine Pitrouc345ce12011-12-16 12:28:32 +0100802 if (err == EAGAIN)
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000803 Py_RETURN_NONE;
Antoine Pitrouc345ce12011-12-16 12:28:32 +0100804 errno = err;
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000805 PyErr_SetFromErrno(PyExc_IOError);
806 return NULL;
807 }
Guido van Rossuma9e20242007-03-08 00:43:48 +0000808
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000809 return PyLong_FromSsize_t(n);
Guido van Rossuma9e20242007-03-08 00:43:48 +0000810}
811
Guido van Rossum53807da2007-04-10 19:01:47 +0000812/* XXX Windows support below is likely incomplete */
813
Guido van Rossum53807da2007-04-10 19:01:47 +0000814/* Cribbed from posix_lseek() */
815static PyObject *
816portable_lseek(int fd, PyObject *posobj, int whence)
817{
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000818 Py_off_t pos, res;
Guido van Rossum53807da2007-04-10 19:01:47 +0000819
820#ifdef SEEK_SET
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000821 /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
822 switch (whence) {
Guido van Rossum53807da2007-04-10 19:01:47 +0000823#if SEEK_SET != 0
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000824 case 0: whence = SEEK_SET; break;
Guido van Rossum53807da2007-04-10 19:01:47 +0000825#endif
826#if SEEK_CUR != 1
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000827 case 1: whence = SEEK_CUR; break;
Guido van Rossum53807da2007-04-10 19:01:47 +0000828#endif
Antoine Pitrou4f7945f2009-01-20 11:42:11 +0000829#if SEEK_END != 2
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000830 case 2: whence = SEEK_END; break;
Guido van Rossum53807da2007-04-10 19:01:47 +0000831#endif
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000832 }
Guido van Rossum53807da2007-04-10 19:01:47 +0000833#endif /* SEEK_SET */
834
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000835 if (posobj == NULL)
836 pos = 0;
837 else {
838 if(PyFloat_Check(posobj)) {
839 PyErr_SetString(PyExc_TypeError, "an integer is required");
840 return NULL;
841 }
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000842#if defined(HAVE_LARGEFILE_SUPPORT)
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000843 pos = PyLong_AsLongLong(posobj);
Guido van Rossum53807da2007-04-10 19:01:47 +0000844#else
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000845 pos = PyLong_AsLong(posobj);
Guido van Rossum53807da2007-04-10 19:01:47 +0000846#endif
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000847 if (PyErr_Occurred())
848 return NULL;
849 }
Guido van Rossum53807da2007-04-10 19:01:47 +0000850
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000851 if (_PyVerify_fd(fd)) {
852 Py_BEGIN_ALLOW_THREADS
Guido van Rossum53807da2007-04-10 19:01:47 +0000853#if defined(MS_WIN64) || defined(MS_WINDOWS)
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000854 res = _lseeki64(fd, pos, whence);
Guido van Rossum53807da2007-04-10 19:01:47 +0000855#else
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000856 res = lseek(fd, pos, whence);
Guido van Rossum53807da2007-04-10 19:01:47 +0000857#endif
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000858 Py_END_ALLOW_THREADS
859 } else
860 res = -1;
861 if (res < 0)
862 return PyErr_SetFromErrno(PyExc_IOError);
Guido van Rossum53807da2007-04-10 19:01:47 +0000863
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000864#if defined(HAVE_LARGEFILE_SUPPORT)
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000865 return PyLong_FromLongLong(res);
Alexandre Vassalotti77250f42008-05-06 19:48:38 +0000866#else
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000867 return PyLong_FromLong(res);
Guido van Rossum53807da2007-04-10 19:01:47 +0000868#endif
869}
870
Guido van Rossuma9e20242007-03-08 00:43:48 +0000871static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000872fileio_seek(fileio *self, PyObject *args)
Guido van Rossuma9e20242007-03-08 00:43:48 +0000873{
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000874 PyObject *posobj;
875 int whence = 0;
Guido van Rossuma9e20242007-03-08 00:43:48 +0000876
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000877 if (self->fd < 0)
878 return err_closed();
Guido van Rossuma9e20242007-03-08 00:43:48 +0000879
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000880 if (!PyArg_ParseTuple(args, "O|i", &posobj, &whence))
881 return NULL;
Guido van Rossuma9e20242007-03-08 00:43:48 +0000882
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000883 return portable_lseek(self->fd, posobj, whence);
Guido van Rossuma9e20242007-03-08 00:43:48 +0000884}
885
886static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000887fileio_tell(fileio *self, PyObject *args)
Guido van Rossuma9e20242007-03-08 00:43:48 +0000888{
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000889 if (self->fd < 0)
890 return err_closed();
Guido van Rossuma9e20242007-03-08 00:43:48 +0000891
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000892 return portable_lseek(self->fd, NULL, 1);
Guido van Rossuma9e20242007-03-08 00:43:48 +0000893}
894
Thomas Hellerc6a55ee2007-07-11 12:45:46 +0000895#ifdef HAVE_FTRUNCATE
Guido van Rossuma9e20242007-03-08 00:43:48 +0000896static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000897fileio_truncate(fileio *self, PyObject *args)
Guido van Rossuma9e20242007-03-08 00:43:48 +0000898{
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000899 PyObject *posobj = NULL; /* the new size wanted by the user */
Antoine Pitrou905a2ff2010-01-31 22:47:27 +0000900#ifndef MS_WINDOWS
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000901 Py_off_t pos;
Antoine Pitrou905a2ff2010-01-31 22:47:27 +0000902#endif
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000903 int ret;
904 int fd;
Guido van Rossuma9e20242007-03-08 00:43:48 +0000905
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000906 fd = self->fd;
907 if (fd < 0)
908 return err_closed();
909 if (!self->writable)
910 return err_mode("writing");
Guido van Rossuma9e20242007-03-08 00:43:48 +0000911
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000912 if (!PyArg_ParseTuple(args, "|O", &posobj))
913 return NULL;
Guido van Rossum53807da2007-04-10 19:01:47 +0000914
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000915 if (posobj == Py_None || posobj == NULL) {
916 /* Get the current position. */
917 posobj = portable_lseek(fd, NULL, 1);
918 if (posobj == NULL)
919 return NULL;
920 }
921 else {
922 Py_INCREF(posobj);
923 }
Guido van Rossum53807da2007-04-10 19:01:47 +0000924
Thomas Hellerfdeee3a2007-07-12 11:21:36 +0000925#ifdef MS_WINDOWS
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000926 /* MS _chsize doesn't work if newsize doesn't fit in 32 bits,
927 so don't even try using it. */
928 {
929 PyObject *oldposobj, *tempposobj;
930 HANDLE hFile;
Antoine Pitrou905a2ff2010-01-31 22:47:27 +0000931
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000932 /* we save the file pointer position */
933 oldposobj = portable_lseek(fd, NULL, 1);
934 if (oldposobj == NULL) {
935 Py_DECREF(posobj);
936 return NULL;
937 }
Thomas Hellerfdeee3a2007-07-12 11:21:36 +0000938
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000939 /* we then move to the truncation position */
940 tempposobj = portable_lseek(fd, posobj, 0);
941 if (tempposobj == NULL) {
942 Py_DECREF(oldposobj);
943 Py_DECREF(posobj);
944 return NULL;
945 }
946 Py_DECREF(tempposobj);
Antoine Pitrou905a2ff2010-01-31 22:47:27 +0000947
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000948 /* Truncate. Note that this may grow the file! */
949 Py_BEGIN_ALLOW_THREADS
950 errno = 0;
951 hFile = (HANDLE)_get_osfhandle(fd);
952 ret = hFile == (HANDLE)-1; /* testing for INVALID_HANDLE value */
953 if (ret == 0) {
954 ret = SetEndOfFile(hFile) == 0;
955 if (ret)
956 errno = EACCES;
957 }
958 Py_END_ALLOW_THREADS
959
960 /* we restore the file pointer position in any case */
961 tempposobj = portable_lseek(fd, oldposobj, 0);
962 Py_DECREF(oldposobj);
963 if (tempposobj == NULL) {
964 Py_DECREF(posobj);
965 return NULL;
966 }
967 Py_DECREF(tempposobj);
968 }
Thomas Hellerfdeee3a2007-07-12 11:21:36 +0000969#else
Antoine Pitrou905a2ff2010-01-31 22:47:27 +0000970
971#if defined(HAVE_LARGEFILE_SUPPORT)
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000972 pos = PyLong_AsLongLong(posobj);
Antoine Pitrou905a2ff2010-01-31 22:47:27 +0000973#else
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000974 pos = PyLong_AsLong(posobj);
Antoine Pitrou905a2ff2010-01-31 22:47:27 +0000975#endif
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000976 if (PyErr_Occurred()){
977 Py_DECREF(posobj);
978 return NULL;
979 }
Antoine Pitrou905a2ff2010-01-31 22:47:27 +0000980
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000981 Py_BEGIN_ALLOW_THREADS
982 errno = 0;
983 ret = ftruncate(fd, pos);
984 Py_END_ALLOW_THREADS
Antoine Pitrou905a2ff2010-01-31 22:47:27 +0000985
Thomas Hellerfdeee3a2007-07-12 11:21:36 +0000986#endif /* !MS_WINDOWS */
Guido van Rossuma9e20242007-03-08 00:43:48 +0000987
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000988 if (ret != 0) {
989 Py_DECREF(posobj);
990 PyErr_SetFromErrno(PyExc_IOError);
991 return NULL;
992 }
Guido van Rossuma9e20242007-03-08 00:43:48 +0000993
Antoine Pitrouae4b4722010-05-05 16:31:07 +0000994 return posobj;
Guido van Rossuma9e20242007-03-08 00:43:48 +0000995}
Antoine Pitrou905a2ff2010-01-31 22:47:27 +0000996#endif /* HAVE_FTRUNCATE */
Guido van Rossum53807da2007-04-10 19:01:47 +0000997
998static char *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000999mode_string(fileio *self)
Guido van Rossum53807da2007-04-10 19:01:47 +00001000{
Charles-François Natalidc3044c2012-01-09 22:40:02 +01001001 if (self->created) {
1002 if (self->readable)
1003 return "xb+";
1004 else
1005 return "xb";
1006 }
Antoine Pitrouae4b4722010-05-05 16:31:07 +00001007 if (self->readable) {
1008 if (self->writable)
1009 return "rb+";
1010 else
1011 return "rb";
1012 }
1013 else
1014 return "wb";
Guido van Rossum53807da2007-04-10 19:01:47 +00001015}
Guido van Rossuma9e20242007-03-08 00:43:48 +00001016
1017static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001018fileio_repr(fileio *self)
Guido van Rossuma9e20242007-03-08 00:43:48 +00001019{
Martin v. Löwis767046a2011-10-14 15:35:36 +02001020 _Py_IDENTIFIER(name);
Antoine Pitrouae4b4722010-05-05 16:31:07 +00001021 PyObject *nameobj, *res;
Guido van Rossuma9e20242007-03-08 00:43:48 +00001022
Antoine Pitrouae4b4722010-05-05 16:31:07 +00001023 if (self->fd < 0)
1024 return PyUnicode_FromFormat("<_io.FileIO [closed]>");
Antoine Pitrou716c4442009-05-23 19:04:03 +00001025
Martin v. Löwis767046a2011-10-14 15:35:36 +02001026 nameobj = _PyObject_GetAttrId((PyObject *) self, &PyId_name);
Antoine Pitrouae4b4722010-05-05 16:31:07 +00001027 if (nameobj == NULL) {
1028 if (PyErr_ExceptionMatches(PyExc_AttributeError))
1029 PyErr_Clear();
1030 else
1031 return NULL;
1032 res = PyUnicode_FromFormat("<_io.FileIO fd=%d mode='%s'>",
1033 self->fd, mode_string(self));
1034 }
1035 else {
1036 res = PyUnicode_FromFormat("<_io.FileIO name=%R mode='%s'>",
1037 nameobj, mode_string(self));
1038 Py_DECREF(nameobj);
1039 }
1040 return res;
Guido van Rossuma9e20242007-03-08 00:43:48 +00001041}
1042
1043static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001044fileio_isatty(fileio *self)
Guido van Rossuma9e20242007-03-08 00:43:48 +00001045{
Antoine Pitrouae4b4722010-05-05 16:31:07 +00001046 long res;
Guido van Rossum53807da2007-04-10 19:01:47 +00001047
Antoine Pitrouae4b4722010-05-05 16:31:07 +00001048 if (self->fd < 0)
1049 return err_closed();
1050 Py_BEGIN_ALLOW_THREADS
1051 res = isatty(self->fd);
1052 Py_END_ALLOW_THREADS
1053 return PyBool_FromLong(res);
Guido van Rossuma9e20242007-03-08 00:43:48 +00001054}
1055
Antoine Pitrou243757e2010-11-05 21:15:39 +00001056static PyObject *
1057fileio_getstate(fileio *self)
1058{
1059 PyErr_Format(PyExc_TypeError,
1060 "cannot serialize '%s' object", Py_TYPE(self)->tp_name);
1061 return NULL;
1062}
1063
Guido van Rossuma9e20242007-03-08 00:43:48 +00001064
1065PyDoc_STRVAR(fileio_doc,
Ross Lagerwall59142db2011-10-31 20:34:46 +02001066"file(name: str[, mode: str][, opener: None]) -> file IO object\n"
Guido van Rossuma9e20242007-03-08 00:43:48 +00001067"\n"
Charles-François Natalidc3044c2012-01-09 22:40:02 +01001068"Open a file. The mode can be 'r', 'w', 'x' or 'a' for reading (default),\n"
1069"writing, creating or appending. The file will be created if it doesn't\n"
1070"exist when opened for writing or appending; it will be truncated when\n"
1071"opened for writing. A `FileExistsError` will be raised if it already\n"
1072"exists when opened for creating. Opening a file for creating implies\n"
1073"writing so this mode behaves in a similar way to 'w'.Add a '+' to the mode\n"
1074"to allow simultaneous reading and writing. A custom opener can be used by\n"
1075"passing a callable as *opener*. The underlying file descriptor for the file\n"
Ross Lagerwall59142db2011-10-31 20:34:46 +02001076"object is then obtained by calling opener with (*name*, *flags*).\n"
Charles-François Natalidc3044c2012-01-09 22:40:02 +01001077"*opener* must return an open file descriptor (passing os.open as *opener*\n"
1078"results in functionality similar to passing None).");
Guido van Rossuma9e20242007-03-08 00:43:48 +00001079
1080PyDoc_STRVAR(read_doc,
1081"read(size: int) -> bytes. read at most size bytes, returned as bytes.\n"
1082"\n"
1083"Only makes one system call, so less data may be returned than requested\n"
Guido van Rossum7165cb12007-07-10 06:54:34 +00001084"In non-blocking mode, returns None if no data is available.\n"
1085"On end-of-file, returns ''.");
1086
1087PyDoc_STRVAR(readall_doc,
1088"readall() -> bytes. read all data from the file, returned as bytes.\n"
1089"\n"
1090"In non-blocking mode, returns as much as is immediately available,\n"
1091"or None if no data is available. On end-of-file, returns ''.");
Guido van Rossuma9e20242007-03-08 00:43:48 +00001092
1093PyDoc_STRVAR(write_doc,
1094"write(b: bytes) -> int. Write bytes b to file, return number written.\n"
1095"\n"
1096"Only makes one system call, so not all of the data may be written.\n"
1097"The number of bytes actually written is returned.");
1098
1099PyDoc_STRVAR(fileno_doc,
1100"fileno() -> int. \"file descriptor\".\n"
1101"\n"
1102"This is needed for lower-level file interfaces, such the fcntl module.");
1103
1104PyDoc_STRVAR(seek_doc,
1105"seek(offset: int[, whence: int]) -> None. Move to new file position.\n"
1106"\n"
1107"Argument offset is a byte count. Optional argument whence defaults to\n"
1108"0 (offset from start of file, offset should be >= 0); other values are 1\n"
1109"(move relative to current position, positive or negative), and 2 (move\n"
1110"relative to end of file, usually negative, although many platforms allow\n"
1111"seeking beyond the end of a file)."
1112"\n"
1113"Note that not all file objects are seekable.");
1114
Thomas Hellerc6a55ee2007-07-11 12:45:46 +00001115#ifdef HAVE_FTRUNCATE
Guido van Rossuma9e20242007-03-08 00:43:48 +00001116PyDoc_STRVAR(truncate_doc,
Antoine Pitrouae4b4722010-05-05 16:31:07 +00001117"truncate([size: int]) -> None. Truncate the file to at most size bytes.\n"
Guido van Rossuma9e20242007-03-08 00:43:48 +00001118"\n"
Alexandre Vassalotti77250f42008-05-06 19:48:38 +00001119"Size defaults to the current file position, as returned by tell()."
1120"The current file position is changed to the value of size.");
Thomas Hellerc6a55ee2007-07-11 12:45:46 +00001121#endif
Guido van Rossuma9e20242007-03-08 00:43:48 +00001122
1123PyDoc_STRVAR(tell_doc,
Antoine Pitrouae4b4722010-05-05 16:31:07 +00001124"tell() -> int. Current file position");
Guido van Rossuma9e20242007-03-08 00:43:48 +00001125
1126PyDoc_STRVAR(readinto_doc,
Benjamin Peterson9a8082f2009-03-05 00:55:56 +00001127"readinto() -> Same as RawIOBase.readinto().");
Guido van Rossuma9e20242007-03-08 00:43:48 +00001128
1129PyDoc_STRVAR(close_doc,
1130"close() -> None. Close the file.\n"
1131"\n"
1132"A closed file cannot be used for further I/O operations. close() may be\n"
1133"called more than once without error. Changes the fileno to -1.");
1134
1135PyDoc_STRVAR(isatty_doc,
1136"isatty() -> bool. True if the file is connected to a tty device.");
1137
Guido van Rossuma9e20242007-03-08 00:43:48 +00001138PyDoc_STRVAR(seekable_doc,
1139"seekable() -> bool. True if file supports random-access.");
1140
1141PyDoc_STRVAR(readable_doc,
1142"readable() -> bool. True if file was opened in a read mode.");
1143
1144PyDoc_STRVAR(writable_doc,
1145"writable() -> bool. True if file was opened in a write mode.");
1146
1147static PyMethodDef fileio_methods[] = {
Antoine Pitrouae4b4722010-05-05 16:31:07 +00001148 {"read", (PyCFunction)fileio_read, METH_VARARGS, read_doc},
1149 {"readall", (PyCFunction)fileio_readall, METH_NOARGS, readall_doc},
1150 {"readinto", (PyCFunction)fileio_readinto, METH_VARARGS, readinto_doc},
1151 {"write", (PyCFunction)fileio_write, METH_VARARGS, write_doc},
1152 {"seek", (PyCFunction)fileio_seek, METH_VARARGS, seek_doc},
1153 {"tell", (PyCFunction)fileio_tell, METH_VARARGS, tell_doc},
Thomas Hellerc6a55ee2007-07-11 12:45:46 +00001154#ifdef HAVE_FTRUNCATE
Antoine Pitrouae4b4722010-05-05 16:31:07 +00001155 {"truncate", (PyCFunction)fileio_truncate, METH_VARARGS, truncate_doc},
Thomas Hellerc6a55ee2007-07-11 12:45:46 +00001156#endif
Antoine Pitrouae4b4722010-05-05 16:31:07 +00001157 {"close", (PyCFunction)fileio_close, METH_NOARGS, close_doc},
1158 {"seekable", (PyCFunction)fileio_seekable, METH_NOARGS, seekable_doc},
1159 {"readable", (PyCFunction)fileio_readable, METH_NOARGS, readable_doc},
1160 {"writable", (PyCFunction)fileio_writable, METH_NOARGS, writable_doc},
1161 {"fileno", (PyCFunction)fileio_fileno, METH_NOARGS, fileno_doc},
1162 {"isatty", (PyCFunction)fileio_isatty, METH_NOARGS, isatty_doc},
Antoine Pitroue033e062010-10-29 10:38:18 +00001163 {"_dealloc_warn", (PyCFunction)fileio_dealloc_warn, METH_O, NULL},
Antoine Pitrou243757e2010-11-05 21:15:39 +00001164 {"__getstate__", (PyCFunction)fileio_getstate, METH_NOARGS, NULL},
Antoine Pitrouae4b4722010-05-05 16:31:07 +00001165 {NULL, NULL} /* sentinel */
Guido van Rossuma9e20242007-03-08 00:43:48 +00001166};
1167
Guido van Rossum53807da2007-04-10 19:01:47 +00001168/* 'closed' and 'mode' are attributes for backwards compatibility reasons. */
1169
Guido van Rossumb0428152007-04-08 17:44:42 +00001170static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001171get_closed(fileio *self, void *closure)
Guido van Rossumb0428152007-04-08 17:44:42 +00001172{
Antoine Pitrouae4b4722010-05-05 16:31:07 +00001173 return PyBool_FromLong((long)(self->fd < 0));
Guido van Rossum53807da2007-04-10 19:01:47 +00001174}
1175
1176static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001177get_closefd(fileio *self, void *closure)
Christian Heimesecc42a22008-11-05 19:30:32 +00001178{
Antoine Pitrouae4b4722010-05-05 16:31:07 +00001179 return PyBool_FromLong((long)(self->closefd));
Christian Heimesecc42a22008-11-05 19:30:32 +00001180}
1181
1182static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001183get_mode(fileio *self, void *closure)
Guido van Rossum53807da2007-04-10 19:01:47 +00001184{
Antoine Pitrouae4b4722010-05-05 16:31:07 +00001185 return PyUnicode_FromString(mode_string(self));
Guido van Rossumb0428152007-04-08 17:44:42 +00001186}
1187
1188static PyGetSetDef fileio_getsetlist[] = {
Antoine Pitrouae4b4722010-05-05 16:31:07 +00001189 {"closed", (getter)get_closed, NULL, "True if the file is closed"},
1190 {"closefd", (getter)get_closefd, NULL,
1191 "True if the file descriptor will be closed"},
1192 {"mode", (getter)get_mode, NULL, "String giving the file mode"},
1193 {NULL},
Guido van Rossumb0428152007-04-08 17:44:42 +00001194};
1195
Guido van Rossuma9e20242007-03-08 00:43:48 +00001196PyTypeObject PyFileIO_Type = {
Antoine Pitrouae4b4722010-05-05 16:31:07 +00001197 PyVarObject_HEAD_INIT(NULL, 0)
1198 "_io.FileIO",
1199 sizeof(fileio),
1200 0,
1201 (destructor)fileio_dealloc, /* tp_dealloc */
1202 0, /* tp_print */
1203 0, /* tp_getattr */
1204 0, /* tp_setattr */
1205 0, /* tp_reserved */
1206 (reprfunc)fileio_repr, /* tp_repr */
1207 0, /* tp_as_number */
1208 0, /* tp_as_sequence */
1209 0, /* tp_as_mapping */
1210 0, /* tp_hash */
1211 0, /* tp_call */
1212 0, /* tp_str */
1213 PyObject_GenericGetAttr, /* tp_getattro */
1214 0, /* tp_setattro */
1215 0, /* tp_as_buffer */
1216 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
1217 | Py_TPFLAGS_HAVE_GC, /* tp_flags */
1218 fileio_doc, /* tp_doc */
1219 (traverseproc)fileio_traverse, /* tp_traverse */
1220 (inquiry)fileio_clear, /* tp_clear */
1221 0, /* tp_richcompare */
1222 offsetof(fileio, weakreflist), /* tp_weaklistoffset */
1223 0, /* tp_iter */
1224 0, /* tp_iternext */
1225 fileio_methods, /* tp_methods */
1226 0, /* tp_members */
1227 fileio_getsetlist, /* tp_getset */
1228 0, /* tp_base */
1229 0, /* tp_dict */
1230 0, /* tp_descr_get */
1231 0, /* tp_descr_set */
1232 offsetof(fileio, dict), /* tp_dictoffset */
1233 fileio_init, /* tp_init */
1234 PyType_GenericAlloc, /* tp_alloc */
1235 fileio_new, /* tp_new */
1236 PyObject_GC_Del, /* tp_free */
Guido van Rossuma9e20242007-03-08 00:43:48 +00001237};