diff options
author | Antoine Pitrou <solipsis@pitrou.net> | 2014-06-30 00:07:28 (GMT) |
---|---|---|
committer | Antoine Pitrou <solipsis@pitrou.net> | 2014-06-30 00:07:28 (GMT) |
commit | de68722ca06615692613148b7015b3c62cd043c3 (patch) | |
tree | 40ee136de88cdf028fcc75ca03422b77a6a2fc90 /Modules/_io/fileio.c | |
parent | d95224ceaf61b6c4cbc7fd8e851a1268f6eee914 (diff) | |
download | cpython-de68722ca06615692613148b7015b3c62cd043c3.zip cpython-de68722ca06615692613148b7015b3c62cd043c3.tar.gz cpython-de68722ca06615692613148b7015b3c62cd043c3.tar.bz2 |
Issue #21679: Prevent extraneous fstat() calls during open(). Patch by Bohuslav Kabrda.
Diffstat (limited to 'Modules/_io/fileio.c')
-rw-r--r-- | Modules/_io/fileio.c | 46 |
1 files changed, 25 insertions, 21 deletions
diff --git a/Modules/_io/fileio.c b/Modules/_io/fileio.c index cbb2daf..038b2c6 100644 --- a/Modules/_io/fileio.c +++ b/Modules/_io/fileio.c @@ -53,6 +53,7 @@ typedef struct { signed int seekable : 2; /* -1 means unknown */ unsigned int closefd : 1; char finalizing; + unsigned int blksize; PyObject *weakreflist; PyObject *dict; } fileio; @@ -161,6 +162,7 @@ fileio_new(PyTypeObject *type, PyObject *args, PyObject *kwds) self->writable = 0; self->appending = 0; self->seekable = -1; + self->blksize = 0; self->closefd = 1; self->weakreflist = NULL; } @@ -168,26 +170,6 @@ fileio_new(PyTypeObject *type, PyObject *args, PyObject *kwds) return (PyObject *) self; } -/* On Unix, open will succeed for directories. - In Python, there should be no file objects referring to - directories, so we need a check. */ - -static int -dircheck(fileio* self, PyObject *nameobj) -{ -#if defined(HAVE_FSTAT) && defined(S_ISDIR) && defined(EISDIR) - struct stat buf; - if (self->fd < 0) - return 0; - if (fstat(self->fd, &buf) == 0 && S_ISDIR(buf.st_mode)) { - errno = EISDIR; - PyErr_SetFromErrnoWithFilenameObject(PyExc_IOError, nameobj); - return -1; - } -#endif - return 0; -} - static int check_fd(int fd) { @@ -233,6 +215,9 @@ fileio_init(PyObject *oself, PyObject *args, PyObject *kwds) #elif !defined(MS_WINDOWS) int *atomic_flag_works = NULL; #endif +#ifdef HAVE_FSTAT + struct stat fdfstat; +#endif assert(PyFileIO_Check(oself)); if (self->fd >= 0) { @@ -421,8 +406,26 @@ fileio_init(PyObject *oself, PyObject *args, PyObject *kwds) goto error; #endif } - if (dircheck(self, nameobj) < 0) + + self->blksize = DEFAULT_BUFFER_SIZE; +#ifdef HAVE_FSTAT + if (fstat(self->fd, &fdfstat) < 0) goto error; +#if defined(S_ISDIR) && defined(EISDIR) + /* On Unix, open will succeed for directories. + In Python, there should be no file objects referring to + directories, so we need a check. */ + if (S_ISDIR(fdfstat.st_mode)) { + errno = EISDIR; + PyErr_SetFromErrnoWithFilenameObject(PyExc_IOError, nameobj); + goto error; + } +#endif /* defined(S_ISDIR) */ +#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE + if (fdfstat.st_blksize > 1) + self->blksize = fdfstat.st_blksize; +#endif /* HAVE_STRUCT_STAT_ST_BLKSIZE */ +#endif /* HAVE_FSTAT */ #if defined(MS_WINDOWS) || defined(__CYGWIN__) /* don't translate newlines (\r\n <=> \n) */ @@ -1216,6 +1219,7 @@ static PyGetSetDef fileio_getsetlist[] = { }; static PyMemberDef fileio_members[] = { + {"_blksize", T_UINT, offsetof(fileio, blksize), 0}, {"_finalizing", T_BOOL, offsetof(fileio, finalizing), 0}, {NULL} }; |