|
43 | 43 | # include <limits.h>
|
44 | 44 | #endif
|
45 | 45 |
|
| 46 | +#ifdef __linux__ |
| 47 | +# include <sys/sysmacros.h> |
| 48 | +#endif |
| 49 | + |
46 | 50 | #define php_stream_fopen_from_fd_int(fd, mode, persistent_id) _php_stream_fopen_from_fd_int((fd), (mode), (persistent_id) STREAMS_CC)
|
47 | 51 | #define php_stream_fopen_from_fd_int_rel(fd, mode, persistent_id) _php_stream_fopen_from_fd_int((fd), (mode), (persistent_id) STREAMS_REL_CC)
|
48 | 52 | #define php_stream_fopen_from_file_int(file, mode) _php_stream_fopen_from_file_int((file), (mode) STREAMS_CC)
|
@@ -255,7 +259,28 @@ PHPAPI php_stream *_php_stream_fopen_tmpfile(int dummy STREAMS_DC)
|
255 | 259 | static void detect_is_seekable(php_stdio_stream_data *self) {
|
256 | 260 | #if defined(S_ISFIFO) && defined(S_ISCHR)
|
257 | 261 | if (self->fd >= 0 && do_fstat(self, 0) == 0) {
|
| 262 | +#ifdef __linux__ |
| 263 | + if (S_ISCHR(self->sb.st_mode)) { |
| 264 | + /* Some character devices are exceptions, check their major/minor ID |
| 265 | + * https://www.kernel.org/doc/Documentation/admin-guide/devices.txt */ |
| 266 | + if (major(self->sb.st_rdev) == 1) { |
| 267 | + unsigned m = minor(self->sb.st_rdev); |
| 268 | + self->is_seekable = |
| 269 | + m == 1 || /* /dev/mem */ |
| 270 | + m == 2 || /* /dev/kmem */ |
| 271 | + m == 3 || /* /dev/null */ |
| 272 | + m == 4 || /* /dev/port (seekable, offset = I/O port) */ |
| 273 | + m == 5 || /* /dev/zero */ |
| 274 | + m == 7; /* /dev/full */ |
| 275 | + } else { |
| 276 | + self->is_seekable = false; |
| 277 | + } |
| 278 | + } else { |
| 279 | + self->is_seekable = !S_ISFIFO(self->sb.st_mode); |
| 280 | + } |
| 281 | +#else |
258 | 282 | self->is_seekable = !(S_ISFIFO(self->sb.st_mode) || S_ISCHR(self->sb.st_mode));
|
| 283 | +#endif |
259 | 284 | self->is_pipe = S_ISFIFO(self->sb.st_mode);
|
260 | 285 | }
|
261 | 286 | #elif defined(PHP_WIN32)
|
|
0 commit comments