summaryrefslogtreecommitdiffstats
path: root/Modules/_io/fileio.c
diff options
context:
space:
mode:
authorAntoine Pitrou <solipsis@pitrou.net>2014-06-30 00:07:28 (GMT)
committerAntoine Pitrou <solipsis@pitrou.net>2014-06-30 00:07:28 (GMT)
commitde68722ca06615692613148b7015b3c62cd043c3 (patch)
tree40ee136de88cdf028fcc75ca03422b77a6a2fc90 /Modules/_io/fileio.c
parentd95224ceaf61b6c4cbc7fd8e851a1268f6eee914 (diff)
downloadcpython-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.c46
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}
};