From: Nikita Popov Date: Wed, 17 Jul 2019 12:43:53 +0000 (+0200) Subject: Avoid duplicate fstat() for includes X-Git-Tag: php-7.4.0beta1~77 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=07a4d134abd07690f9921eb0d0c7eeb671b0b875;p=php Avoid duplicate fstat() for includes By adding a flag to avoid forced fstat for includes. The two fstats will happen back to back and we don't care about a possible invalidation. I was hoping to move this higher up in the stack and make the ISREG check somewhere in fsizer of fixup, but this doesn't really seem to be possible. E.g. an FP stdin handle will not be a regular file but of course needs to be allowed. Additionally custom stream wrappers may not implement this functionality. --- diff --git a/main/streams/plain_wrapper.c b/main/streams/plain_wrapper.c index 1bfb2129dc..e0bc980e5d 100644 --- a/main/streams/plain_wrapper.c +++ b/main/streams/plain_wrapper.c @@ -128,6 +128,7 @@ typedef struct { unsigned is_pipe:1; /* don't try and seek */ unsigned cached_fstat:1; /* sb is valid */ unsigned is_pipe_blocking:1; /* allow blocking read() on pipes, currently Windows only */ + unsigned no_forced_fstat:1; /* Use fstat cache even if forced */ unsigned _reserved:28; int lock_flag; /* stores the lock state */ @@ -152,7 +153,7 @@ typedef struct { static int do_fstat(php_stdio_stream_data *d, int force) { - if (!d->cached_fstat || force) { + if (!d->cached_fstat || (force && !d->no_forced_fstat)) { int fd; int r; @@ -1079,6 +1080,10 @@ PHPAPI php_stream *_php_stream_fopen(const char *filename, const char *mode, zen php_stream_close(ret); return NULL; } + + /* Make sure the fstat result is reused when we later try to get the + * file size. */ + self->no_forced_fstat = 1; } if (options & STREAM_USE_BLOCKING_PIPE) {