From 5aad60bfe676766d005d9abbe5908d84f1f614f0 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Fri, 29 Apr 2022 05:22:53 +0200 Subject: [PATCH] main/streams/plain_wrapper: skip lseek(SEEK_CUR) for newly opened files A file that has just been opened is known to be at offset zero, and the lseek(SEEK_CUR) system call to determine the current offset can be skipped. --- main/php_streams.h | 2 +- main/streams/php_stream_plain_wrapper.h | 4 ++-- main/streams/plain_wrapper.c | 12 ++++++++++-- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/main/php_streams.h b/main/php_streams.h index 3742290218e95..8e7bbf6e563be 100644 --- a/main/php_streams.h +++ b/main/php_streams.h @@ -65,7 +65,7 @@ END_EXTERN_C() #define php_stream_fopen_with_path_rel(filename, mode, path, opened, options) _php_stream_fopen_with_path((filename), (mode), (path), (opened), (options) STREAMS_REL_CC) -#define php_stream_fopen_from_fd_rel(fd, mode, persistent_id) _php_stream_fopen_from_fd((fd), (mode), (persistent_id) STREAMS_REL_CC) +#define php_stream_fopen_from_fd_rel(fd, mode, persistent_id, zero_position) _php_stream_fopen_from_fd((fd), (mode), (persistent_id), (zero_position) STREAMS_REL_CC) #define php_stream_fopen_from_file_rel(file, mode) _php_stream_fopen_from_file((file), (mode) STREAMS_REL_CC) #define php_stream_fopen_from_pipe_rel(file, mode) _php_stream_fopen_from_pipe((file), (mode) STREAMS_REL_CC) diff --git a/main/streams/php_stream_plain_wrapper.h b/main/streams/php_stream_plain_wrapper.h index 8ece063085837..ce1a6e3876d1f 100644 --- a/main/streams/php_stream_plain_wrapper.h +++ b/main/streams/php_stream_plain_wrapper.h @@ -32,8 +32,8 @@ PHPAPI php_stream *_php_stream_fopen_with_path(const char *filename, const char PHPAPI php_stream *_php_stream_fopen_from_file(FILE *file, const char *mode STREAMS_DC); #define php_stream_fopen_from_file(file, mode) _php_stream_fopen_from_file((file), (mode) STREAMS_CC) -PHPAPI php_stream *_php_stream_fopen_from_fd(int fd, const char *mode, const char *persistent_id STREAMS_DC); -#define php_stream_fopen_from_fd(fd, mode, persistent_id) _php_stream_fopen_from_fd((fd), (mode), (persistent_id) STREAMS_CC) +PHPAPI php_stream *_php_stream_fopen_from_fd(int fd, const char *mode, const char *persistent_id, bool zero_position STREAMS_DC); +#define php_stream_fopen_from_fd(fd, mode, persistent_id) _php_stream_fopen_from_fd((fd), (mode), (persistent_id), false STREAMS_CC) PHPAPI php_stream *_php_stream_fopen_from_pipe(FILE *file, const char *mode STREAMS_DC); #define php_stream_fopen_from_pipe(file, mode) _php_stream_fopen_from_pipe((file), (mode) STREAMS_CC) diff --git a/main/streams/plain_wrapper.c b/main/streams/plain_wrapper.c index 54c48d9ee11df..e9a30f3334016 100644 --- a/main/streams/plain_wrapper.c +++ b/main/streams/plain_wrapper.c @@ -274,7 +274,7 @@ static void detect_is_seekable(php_stdio_stream_data *self) { #endif } -PHPAPI php_stream *_php_stream_fopen_from_fd(int fd, const char *mode, const char *persistent_id STREAMS_DC) +PHPAPI php_stream *_php_stream_fopen_from_fd(int fd, const char *mode, const char *persistent_id, bool zero_position STREAMS_DC) { php_stream *stream = php_stream_fopen_from_fd_int_rel(fd, mode, persistent_id); @@ -285,6 +285,9 @@ PHPAPI php_stream *_php_stream_fopen_from_fd(int fd, const char *mode, const cha if (!self->is_seekable) { stream->flags |= PHP_STREAM_FLAG_NO_SEEK; stream->position = -1; + } else if (zero_position) { + ZEND_ASSERT(zend_lseek(self->fd, 0, SEEK_CUR) == 0); + stream->position = 0; } else { stream->position = zend_lseek(self->fd, 0, SEEK_CUR); #ifdef ESPIPE @@ -1141,7 +1144,12 @@ PHPAPI php_stream *_php_stream_fopen(const char *filename, const char *mode, zen if (options & STREAM_OPEN_FOR_INCLUDE) { ret = php_stream_fopen_from_fd_int_rel(fd, mode, persistent_id); } else { - ret = php_stream_fopen_from_fd_rel(fd, mode, persistent_id); + /* skip the lseek(SEEK_CUR) system call to + * determine the current offset because we + * know newly opened files are at offset zero + * (unless the file has been opened in + * O_APPEND mode) */ + ret = php_stream_fopen_from_fd_rel(fd, mode, persistent_id, (open_flags & O_APPEND) == 0); } if (ret) {