~ubuntu-branches/ubuntu/karmic/python3.0/karmic

« back to all changes in this revision

Viewing changes to Modules/_fileio.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2009-02-16 17:18:23 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20090216171823-1d5cm5qnnjvmnzzm
Tags: 3.0.1-0ubuntu1
New upstream version.

Show diffs side-by-side

added added

removed removed

Lines of Context:
27
27
#include <windows.h>
28
28
#endif
29
29
 
 
30
#if BUFSIZ < (8*1024)
 
31
#define SMALLCHUNK (8*1024)
 
32
#elif (BUFSIZ >= (2 << 25))
 
33
#error "unreasonable BUFSIZ > 64MB defined"
 
34
#else
 
35
#define SMALLCHUNK BUFSIZ
 
36
#endif
 
37
 
 
38
#if SIZEOF_INT < 4
 
39
#define BIGCHUNK  (512 * 32)
 
40
#else
 
41
#define BIGCHUNK  (512 * 1024)
 
42
#endif
 
43
 
30
44
typedef struct {
31
45
        PyObject_HEAD
32
46
        int fd;
41
55
 
42
56
#define PyFileIO_Check(op) (PyObject_TypeCheck((op), &PyFileIO_Type))
43
57
 
44
 
/* Returns 0 on success, errno (which is < 0) on failure. */
 
58
static PyObject *
 
59
portable_lseek(int fd, PyObject *posobj, int whence);
 
60
 
 
61
/* Returns 0 on success, -1 with exception set on failure. */
45
62
static int
46
63
internal_close(PyFileIOObject *self)
47
64
{
 
65
        int err = 0;
48
66
        int save_errno = 0;
49
67
        if (self->fd >= 0) {
50
68
                int fd = self->fd;
51
69
                self->fd = -1;
52
70
                Py_BEGIN_ALLOW_THREADS
53
 
                if (close(fd) < 0)
 
71
                err = close(fd);
 
72
                if (err < 0)
54
73
                        save_errno = errno;
55
74
                Py_END_ALLOW_THREADS
56
75
        }
57
 
        return save_errno;
 
76
        if (err < 0) {
 
77
                errno = save_errno;
 
78
                PyErr_SetFromErrno(PyExc_IOError);
 
79
                return -1;
 
80
        }
 
81
        return 0;
58
82
}
59
83
 
60
84
static PyObject *
64
88
                self->fd = -1;
65
89
                Py_RETURN_NONE;
66
90
        }
67
 
        errno = internal_close(self);
68
 
        if (errno < 0) {
69
 
                PyErr_SetFromErrno(PyExc_IOError);
 
91
        if (internal_close(self))
70
92
                return NULL;
71
 
        }
72
93
 
73
94
        Py_RETURN_NONE;
74
95
}
98
119
   directories, so we need a check.  */
99
120
 
100
121
static int
101
 
dircheck(PyFileIOObject* self)
 
122
dircheck(PyFileIOObject* self, char *name)
102
123
{
103
124
#if defined(HAVE_FSTAT) && defined(S_IFDIR) && defined(EISDIR)
104
125
        struct stat buf;
107
128
        if (fstat(self->fd, &buf) == 0 && S_ISDIR(buf.st_mode)) {
108
129
                char *msg = strerror(EISDIR);
109
130
                PyObject *exc;
110
 
                internal_close(self);
 
131
                if (internal_close(self))
 
132
                        return -1;
111
133
 
112
 
                exc = PyObject_CallFunction(PyExc_IOError, "(is)",
113
 
                                            EISDIR, msg);
 
134
                exc = PyObject_CallFunction(PyExc_IOError, "(iss)",
 
135
                                            EISDIR, msg, name);
114
136
                PyErr_SetObject(PyExc_IOError, exc);
115
137
                Py_XDECREF(exc);
116
138
                return -1;
119
141
        return 0;
120
142
}
121
143
 
 
144
static int
 
145
check_fd(int fd)
 
146
{
 
147
#if defined(HAVE_FSTAT)
 
148
        struct stat buf;
 
149
        if (fstat(fd, &buf) < 0 && errno == EBADF) {
 
150
                PyObject *exc;
 
151
                char *msg = strerror(EBADF);
 
152
                exc = PyObject_CallFunction(PyExc_OSError, "(is)",
 
153
                                            EBADF, msg);
 
154
                PyErr_SetObject(PyExc_OSError, exc);
 
155
                Py_XDECREF(exc);
 
156
                return -1;
 
157
        }
 
158
#endif
 
159
        return 0;
 
160
}
 
161
 
122
162
 
123
163
static int
124
164
fileio_init(PyObject *oself, PyObject *args, PyObject *kwds)
151
191
                                        "Negative filedescriptor");
152
192
                        return -1;
153
193
                }
 
194
                if (check_fd(fd))
 
195
                        return -1;
154
196
        }
155
197
        else {
156
198
                PyErr_Clear();
265
307
                Py_END_ALLOW_THREADS
266
308
                if (self->fd < 0) {
267
309
#ifdef MS_WINDOWS
268
 
                        PyErr_SetFromErrnoWithUnicodeFilename(PyExc_IOError, widename);
269
 
#else
270
 
                        PyErr_SetFromErrnoWithFilename(PyExc_IOError, name);
 
310
                        if (widename != NULL)
 
311
                                PyErr_SetFromErrnoWithUnicodeFilename(PyExc_IOError, widename);
 
312
                        else
271
313
#endif
 
314
                                PyErr_SetFromErrnoWithFilename(PyExc_IOError, name);
272
315
                        goto error;
273
316
                }
274
 
                if(dircheck(self) < 0)
275
 
                        goto error;
 
317
                if(dircheck(self, name) < 0)
 
318
                        goto error;
 
319
        }
 
320
 
 
321
        if (append) {
 
322
                /* For consistent behaviour, we explicitly seek to the
 
323
                   end of file (otherwise, it might be done only on the
 
324
                   first write()). */
 
325
                PyObject *pos = portable_lseek(self->fd, NULL, 2);
 
326
                if (pos == NULL)
 
327
                        goto error;
 
328
                Py_DECREF(pos);
276
329
        }
277
330
 
278
331
        goto done;
292
345
                PyObject_ClearWeakRefs((PyObject *) self);
293
346
 
294
347
        if (self->fd >= 0 && self->closefd) {
295
 
                errno = internal_close(self);
296
 
                if (errno < 0) {
297
 
                        PySys_WriteStderr("close failed: [Errno %d] %s\n",
298
 
                                          errno, strerror(errno));
299
 
                }
 
348
                if(internal_close(self))
 
349
                        PyErr_WriteUnraisable((PyObject*)self);
300
350
        }
301
351
 
302
352
        Py_TYPE(self)->tp_free((PyObject *)self);
387
437
        return PyLong_FromSsize_t(n);
388
438
}
389
439
 
390
 
#define DEFAULT_BUFFER_SIZE (8*1024)
391
 
 
392
440
static PyObject *
393
441
fileio_readall(PyFileIOObject *self)
394
442
{
396
444
        Py_ssize_t total = 0;
397
445
        int n;
398
446
 
399
 
        result = PyBytes_FromStringAndSize(NULL, DEFAULT_BUFFER_SIZE);
 
447
        result = PyBytes_FromStringAndSize(NULL, SMALLCHUNK);
400
448
        if (result == NULL)
401
449
                return NULL;
402
450
 
403
451
        while (1) {
404
 
                Py_ssize_t newsize = total + DEFAULT_BUFFER_SIZE;
 
452
                Py_ssize_t newsize = (total < SMALLCHUNK) ? SMALLCHUNK : total;
 
453
 
 
454
                /* Keep doubling until we reach BIGCHUNK;
 
455
                   then keep adding BIGCHUNK. */
 
456
                if (newsize <= BIGCHUNK) {
 
457
                        newsize += newsize;
 
458
                }
 
459
                else {
 
460
                        /* NOTE: overflow impossible due to limits on BUFSIZ */
 
461
                        newsize += BIGCHUNK;
 
462
                }
 
463
 
405
464
                if (PyBytes_GET_SIZE(result) < newsize) {
406
465
                        if (_PyBytes_Resize(&result, newsize) < 0) {
407
466
                                if (total == 0) {
848
907
        0,                                      /* tp_print */
849
908
        0,                                      /* tp_getattr */
850
909
        0,                                      /* tp_setattr */
851
 
        0,                                      /* tp_compare */
 
910
        0,                                      /* tp_reserved */
852
911
        (reprfunc)fileio_repr,                  /* tp_repr */
853
912
        0,                                      /* tp_as_number */
854
913
        0,                                      /* tp_as_sequence */