This source file includes following definitions.
- php_stream_parse_fopen_modes
- do_fstat
- _php_stream_fopen_from_fd_int
- _php_stream_fopen_from_file_int
- _php_stream_fopen_temporary_file
- _php_stream_fopen_tmpfile
- _php_stream_fopen_from_fd
- _php_stream_fopen_from_file
- _php_stream_fopen_from_pipe
- php_stdiop_write
- php_stdiop_read
- php_stdiop_close
- php_stdiop_flush
- php_stdiop_seek
- php_stdiop_cast
- php_stdiop_stat
- php_stdiop_set_option
- php_plain_files_dirstream_read
- php_plain_files_dirstream_close
- php_plain_files_dirstream_rewind
- php_plain_files_dir_opener
- _php_stream_fopen
- php_plain_files_stream_opener
- php_plain_files_url_stater
- php_plain_files_unlink
- php_plain_files_rename
- php_plain_files_mkdir
- php_plain_files_rmdir
- php_plain_files_metadata
- _php_stream_fopen_with_path
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 #include "php.h"
22 #include "php_globals.h"
23 #include "php_network.h"
24 #include "php_open_temporary_file.h"
25 #include "ext/standard/file.h"
26 #include "ext/standard/flock_compat.h"
27 #include "ext/standard/php_filestat.h"
28 #include <stddef.h>
29 #include <fcntl.h>
30 #if HAVE_SYS_WAIT_H
31 #include <sys/wait.h>
32 #endif
33 #if HAVE_SYS_FILE_H
34 #include <sys/file.h>
35 #endif
36 #ifdef HAVE_SYS_MMAN_H
37 #include <sys/mman.h>
38 #endif
39 #include "SAPI.h"
40
41 #include "php_streams_int.h"
42 #ifdef PHP_WIN32
43 # include "win32/winutil.h"
44 # include "win32/time.h"
45 #endif
46
47 #define php_stream_fopen_from_fd_int(fd, mode, persistent_id) _php_stream_fopen_from_fd_int((fd), (mode), (persistent_id) STREAMS_CC)
48 #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)
49 #define php_stream_fopen_from_file_int(file, mode) _php_stream_fopen_from_file_int((file), (mode) STREAMS_CC)
50 #define php_stream_fopen_from_file_int_rel(file, mode) _php_stream_fopen_from_file_int((file), (mode) STREAMS_REL_CC)
51
52 #if !defined(WINDOWS) && !defined(NETWARE)
53 extern int php_get_uid_by_name(const char *name, uid_t *uid);
54 extern int php_get_gid_by_name(const char *name, gid_t *gid);
55 #endif
56
57 #if defined(PHP_WIN32)
58 # define PLAIN_WRAP_BUF_SIZE(st) (((st) > UINT_MAX) ? UINT_MAX : (unsigned int)(st))
59 #else
60 # define PLAIN_WRAP_BUF_SIZE(st) (st)
61 #endif
62
63
64 PHPAPI int php_stream_parse_fopen_modes(const char *mode, int *open_flags)
65 {
66 int flags;
67
68 switch (mode[0]) {
69 case 'r':
70 flags = 0;
71 break;
72 case 'w':
73 flags = O_TRUNC|O_CREAT;
74 break;
75 case 'a':
76 flags = O_CREAT|O_APPEND;
77 break;
78 case 'x':
79 flags = O_CREAT|O_EXCL;
80 break;
81 case 'c':
82 flags = O_CREAT;
83 break;
84 default:
85
86 return FAILURE;
87 }
88
89 if (strchr(mode, '+')) {
90 flags |= O_RDWR;
91 } else if (flags) {
92 flags |= O_WRONLY;
93 } else {
94 flags |= O_RDONLY;
95 }
96
97 #if defined(O_NONBLOCK)
98 if (strchr(mode, 'n')) {
99 flags |= O_NONBLOCK;
100 }
101 #endif
102
103 #if defined(_O_TEXT) && defined(O_BINARY)
104 if (strchr(mode, 't')) {
105 flags |= _O_TEXT;
106 } else {
107 flags |= O_BINARY;
108 }
109 #endif
110
111 *open_flags = flags;
112 return SUCCESS;
113 }
114
115
116
117
118 typedef struct {
119 FILE *file;
120 int fd;
121 unsigned is_process_pipe:1;
122 unsigned is_pipe:1;
123 unsigned cached_fstat:1;
124 unsigned is_pipe_blocking:1;
125 unsigned _reserved:28;
126
127 int lock_flag;
128 zend_string *temp_name;
129
130 #if HAVE_FLUSHIO
131 char last_op;
132 #endif
133
134 #if HAVE_MMAP
135 char *last_mapped_addr;
136 size_t last_mapped_len;
137 #endif
138 #ifdef PHP_WIN32
139 char *last_mapped_addr;
140 HANDLE file_mapping;
141 #endif
142
143 zend_stat_t sb;
144 } php_stdio_stream_data;
145 #define PHP_STDIOP_GET_FD(anfd, data) anfd = (data)->file ? fileno((data)->file) : (data)->fd
146
147 static int do_fstat(php_stdio_stream_data *d, int force)
148 {
149 if (!d->cached_fstat || force) {
150 int fd;
151 int r;
152
153 PHP_STDIOP_GET_FD(fd, d);
154 r = zend_fstat(fd, &d->sb);
155 d->cached_fstat = r == 0;
156
157 return r;
158 }
159 return 0;
160 }
161
162 static php_stream *_php_stream_fopen_from_fd_int(int fd, const char *mode, const char *persistent_id STREAMS_DC)
163 {
164 php_stdio_stream_data *self;
165
166 self = pemalloc_rel_orig(sizeof(*self), persistent_id);
167 memset(self, 0, sizeof(*self));
168 self->file = NULL;
169 self->is_pipe = 0;
170 self->lock_flag = LOCK_UN;
171 self->is_process_pipe = 0;
172 self->temp_name = NULL;
173 self->fd = fd;
174 #ifdef PHP_WIN32
175 self->is_pipe_blocking = 0;
176 #endif
177
178 return php_stream_alloc_rel(&php_stream_stdio_ops, self, persistent_id, mode);
179 }
180
181 static php_stream *_php_stream_fopen_from_file_int(FILE *file, const char *mode STREAMS_DC)
182 {
183 php_stdio_stream_data *self;
184
185 self = emalloc_rel_orig(sizeof(*self));
186 memset(self, 0, sizeof(*self));
187 self->file = file;
188 self->is_pipe = 0;
189 self->lock_flag = LOCK_UN;
190 self->is_process_pipe = 0;
191 self->temp_name = NULL;
192 self->fd = fileno(file);
193 #ifdef PHP_WIN32
194 self->is_pipe_blocking = 0;
195 #endif
196
197 return php_stream_alloc_rel(&php_stream_stdio_ops, self, 0, mode);
198 }
199
200 PHPAPI php_stream *_php_stream_fopen_temporary_file(const char *dir, const char *pfx, zend_string **opened_path_ptr STREAMS_DC)
201 {
202 zend_string *opened_path = NULL;
203 int fd;
204
205 fd = php_open_temporary_fd(dir, pfx, &opened_path);
206 if (fd != -1) {
207 php_stream *stream;
208
209 if (opened_path_ptr) {
210 *opened_path_ptr = opened_path;
211 }
212
213 stream = php_stream_fopen_from_fd_int_rel(fd, "r+b", NULL);
214 if (stream) {
215 php_stdio_stream_data *self = (php_stdio_stream_data*)stream->abstract;
216 stream->wrapper = &php_plain_files_wrapper;
217 stream->orig_path = estrndup(ZSTR_VAL(opened_path), ZSTR_LEN(opened_path));
218
219 self->temp_name = opened_path;
220 self->lock_flag = LOCK_UN;
221
222 return stream;
223 }
224 close(fd);
225
226 php_error_docref(NULL, E_WARNING, "unable to allocate stream");
227
228 return NULL;
229 }
230 return NULL;
231 }
232
233 PHPAPI php_stream *_php_stream_fopen_tmpfile(int dummy STREAMS_DC)
234 {
235 return php_stream_fopen_temporary_file(NULL, "php", NULL);
236 }
237
238 PHPAPI php_stream *_php_stream_fopen_from_fd(int fd, const char *mode, const char *persistent_id STREAMS_DC)
239 {
240 php_stream *stream = php_stream_fopen_from_fd_int_rel(fd, mode, persistent_id);
241
242 if (stream) {
243 php_stdio_stream_data *self = (php_stdio_stream_data*)stream->abstract;
244
245 #ifdef S_ISFIFO
246
247 if (self->fd >= 0) {
248 self->is_pipe = (do_fstat(self, 0) == 0 && S_ISFIFO(self->sb.st_mode)) ? 1 : 0;
249 }
250 #elif defined(PHP_WIN32)
251 {
252 zend_uintptr_t handle = _get_osfhandle(self->fd);
253
254 if (handle != (zend_uintptr_t)INVALID_HANDLE_VALUE) {
255 self->is_pipe = GetFileType((HANDLE)handle) == FILE_TYPE_PIPE;
256 }
257 }
258 #endif
259
260 if (self->is_pipe) {
261 stream->flags |= PHP_STREAM_FLAG_NO_SEEK;
262 } else {
263 stream->position = zend_lseek(self->fd, 0, SEEK_CUR);
264 #ifdef ESPIPE
265 if (stream->position == (zend_off_t)-1 && errno == ESPIPE) {
266 stream->position = 0;
267 stream->flags |= PHP_STREAM_FLAG_NO_SEEK;
268 self->is_pipe = 1;
269 }
270 #endif
271 }
272 }
273
274 return stream;
275 }
276
277 PHPAPI php_stream *_php_stream_fopen_from_file(FILE *file, const char *mode STREAMS_DC)
278 {
279 php_stream *stream = php_stream_fopen_from_file_int_rel(file, mode);
280
281 if (stream) {
282 php_stdio_stream_data *self = (php_stdio_stream_data*)stream->abstract;
283
284 #ifdef S_ISFIFO
285
286 if (self->fd >= 0) {
287 self->is_pipe = (do_fstat(self, 0) == 0 && S_ISFIFO(self->sb.st_mode)) ? 1 : 0;
288 }
289 #elif defined(PHP_WIN32)
290 {
291 zend_uintptr_t handle = _get_osfhandle(self->fd);
292
293 if (handle != (zend_uintptr_t)INVALID_HANDLE_VALUE) {
294 self->is_pipe = GetFileType((HANDLE)handle) == FILE_TYPE_PIPE;
295 }
296 }
297 #endif
298
299 if (self->is_pipe) {
300 stream->flags |= PHP_STREAM_FLAG_NO_SEEK;
301 } else {
302 stream->position = zend_ftell(file);
303 }
304 }
305
306 return stream;
307 }
308
309 PHPAPI php_stream *_php_stream_fopen_from_pipe(FILE *file, const char *mode STREAMS_DC)
310 {
311 php_stdio_stream_data *self;
312 php_stream *stream;
313
314 self = emalloc_rel_orig(sizeof(*self));
315 memset(self, 0, sizeof(*self));
316 self->file = file;
317 self->is_pipe = 1;
318 self->lock_flag = LOCK_UN;
319 self->is_process_pipe = 1;
320 self->fd = fileno(file);
321 self->temp_name = NULL;
322 #ifdef PHP_WIN32
323 self->is_pipe_blocking = 0;
324 #endif
325
326 stream = php_stream_alloc_rel(&php_stream_stdio_ops, self, 0, mode);
327 stream->flags |= PHP_STREAM_FLAG_NO_SEEK;
328 return stream;
329 }
330
331 static size_t php_stdiop_write(php_stream *stream, const char *buf, size_t count)
332 {
333 php_stdio_stream_data *data = (php_stdio_stream_data*)stream->abstract;
334
335 assert(data != NULL);
336
337 if (data->fd >= 0) {
338 #ifdef PHP_WIN32
339 int bytes_written;
340 if (ZEND_SIZE_T_UINT_OVFL(count)) {
341 count = UINT_MAX;
342 }
343 bytes_written = _write(data->fd, buf, (unsigned int)count);
344 #else
345 int bytes_written = write(data->fd, buf, count);
346 #endif
347 if (bytes_written < 0) return 0;
348 return (size_t) bytes_written;
349 } else {
350
351 #if HAVE_FLUSHIO
352 if (!data->is_pipe && data->last_op == 'r') {
353 zend_fseek(data->file, 0, SEEK_CUR);
354 }
355 data->last_op = 'w';
356 #endif
357
358 return fwrite(buf, 1, count, data->file);
359 }
360 }
361
362 static size_t php_stdiop_read(php_stream *stream, char *buf, size_t count)
363 {
364 php_stdio_stream_data *data = (php_stdio_stream_data*)stream->abstract;
365 size_t ret;
366
367 assert(data != NULL);
368
369 if (data->fd >= 0) {
370 #ifdef PHP_WIN32
371 php_stdio_stream_data *self = (php_stdio_stream_data*)stream->abstract;
372
373 if ((self->is_pipe || self->is_process_pipe) && !self->is_pipe_blocking) {
374 HANDLE ph = (HANDLE)_get_osfhandle(data->fd);
375 int retry = 0;
376 DWORD avail_read = 0;
377
378 do {
379
380
381
382 if (!PeekNamedPipe(ph, NULL, 0, NULL, &avail_read, NULL)) {
383 break;
384 }
385
386 if (0 == avail_read) {
387 usleep(10);
388 }
389 } while (0 == avail_read && retry++ < 3200000);
390
391
392
393 if (avail_read < count) {
394 count = avail_read;
395 }
396 }
397 #endif
398 ret = read(data->fd, buf, PLAIN_WRAP_BUF_SIZE(count));
399
400 if (ret == (size_t)-1 && errno == EINTR) {
401
402
403
404 ret = read(data->fd, buf, PLAIN_WRAP_BUF_SIZE(count));
405 }
406
407 stream->eof = (ret == 0 || (ret == (size_t)-1 && errno != EWOULDBLOCK && errno != EINTR && errno != EBADF));
408
409 } else {
410 #if HAVE_FLUSHIO
411 if (!data->is_pipe && data->last_op == 'w')
412 zend_fseek(data->file, 0, SEEK_CUR);
413 data->last_op = 'r';
414 #endif
415
416 ret = fread(buf, 1, count, data->file);
417
418 stream->eof = feof(data->file);
419 }
420 return ret;
421 }
422
423 static int php_stdiop_close(php_stream *stream, int close_handle)
424 {
425 int ret;
426 php_stdio_stream_data *data = (php_stdio_stream_data*)stream->abstract;
427
428 assert(data != NULL);
429
430 #if HAVE_MMAP
431 if (data->last_mapped_addr) {
432 munmap(data->last_mapped_addr, data->last_mapped_len);
433 data->last_mapped_addr = NULL;
434 }
435 #elif defined(PHP_WIN32)
436 if (data->last_mapped_addr) {
437 UnmapViewOfFile(data->last_mapped_addr);
438 data->last_mapped_addr = NULL;
439 }
440 if (data->file_mapping) {
441 CloseHandle(data->file_mapping);
442 data->file_mapping = NULL;
443 }
444 #endif
445
446 if (close_handle) {
447 if (data->file) {
448 if (data->is_process_pipe) {
449 errno = 0;
450 ret = pclose(data->file);
451
452 #if HAVE_SYS_WAIT_H
453 if (WIFEXITED(ret)) {
454 ret = WEXITSTATUS(ret);
455 }
456 #endif
457 } else {
458 ret = fclose(data->file);
459 data->file = NULL;
460 }
461 } else if (data->fd != -1) {
462 ret = close(data->fd);
463 data->fd = -1;
464 } else {
465 return 0;
466 }
467 if (data->temp_name) {
468 unlink(ZSTR_VAL(data->temp_name));
469
470 zend_string_release(data->temp_name);
471 data->temp_name = NULL;
472 }
473 } else {
474 ret = 0;
475 data->file = NULL;
476 data->fd = -1;
477 }
478
479 pefree(data, stream->is_persistent);
480
481 return ret;
482 }
483
484 static int php_stdiop_flush(php_stream *stream)
485 {
486 php_stdio_stream_data *data = (php_stdio_stream_data*)stream->abstract;
487
488 assert(data != NULL);
489
490
491
492
493
494
495 if (data->file) {
496 return fflush(data->file);
497 }
498 return 0;
499 }
500
501 static int php_stdiop_seek(php_stream *stream, zend_off_t offset, int whence, zend_off_t *newoffset)
502 {
503 php_stdio_stream_data *data = (php_stdio_stream_data*)stream->abstract;
504 int ret;
505
506 assert(data != NULL);
507
508 if (data->is_pipe) {
509 php_error_docref(NULL, E_WARNING, "cannot seek on a pipe");
510 return -1;
511 }
512
513 if (data->fd >= 0) {
514 zend_off_t result;
515
516 result = zend_lseek(data->fd, offset, whence);
517 if (result == (zend_off_t)-1)
518 return -1;
519
520 *newoffset = result;
521 return 0;
522
523 } else {
524 ret = zend_fseek(data->file, offset, whence);
525 *newoffset = zend_ftell(data->file);
526 return ret;
527 }
528 }
529
530 static int php_stdiop_cast(php_stream *stream, int castas, void **ret)
531 {
532 php_socket_t fd;
533 php_stdio_stream_data *data = (php_stdio_stream_data*) stream->abstract;
534
535 assert(data != NULL);
536
537
538
539
540 switch (castas) {
541 case PHP_STREAM_AS_STDIO:
542 if (ret) {
543
544 if (data->file == NULL) {
545
546
547 char fixed_mode[5];
548 php_stream_mode_sanitize_fdopen_fopencookie(stream, fixed_mode);
549 data->file = fdopen(data->fd, fixed_mode);
550 if (data->file == NULL) {
551 return FAILURE;
552 }
553 }
554
555 *(FILE**)ret = data->file;
556 data->fd = SOCK_ERR;
557 }
558 return SUCCESS;
559
560 case PHP_STREAM_AS_FD_FOR_SELECT:
561 PHP_STDIOP_GET_FD(fd, data);
562 if (SOCK_ERR == fd) {
563 return FAILURE;
564 }
565 if (ret) {
566 *(php_socket_t *)ret = fd;
567 }
568 return SUCCESS;
569
570 case PHP_STREAM_AS_FD:
571 PHP_STDIOP_GET_FD(fd, data);
572
573 if (SOCK_ERR == fd) {
574 return FAILURE;
575 }
576 if (data->file) {
577 fflush(data->file);
578 }
579 if (ret) {
580 *(php_socket_t *)ret = fd;
581 }
582 return SUCCESS;
583 default:
584 return FAILURE;
585 }
586 }
587
588 static int php_stdiop_stat(php_stream *stream, php_stream_statbuf *ssb)
589 {
590 int ret;
591 php_stdio_stream_data *data = (php_stdio_stream_data*) stream->abstract;
592
593 assert(data != NULL);
594 if((ret = do_fstat(data, 1)) == 0) {
595 memcpy(&ssb->sb, &data->sb, sizeof(ssb->sb));
596 }
597
598 return ret;
599 }
600
601 static int php_stdiop_set_option(php_stream *stream, int option, int value, void *ptrparam)
602 {
603 php_stdio_stream_data *data = (php_stdio_stream_data*) stream->abstract;
604 size_t size;
605 int fd;
606 #ifdef O_NONBLOCK
607
608 int flags;
609 int oldval;
610 #endif
611
612 PHP_STDIOP_GET_FD(fd, data);
613
614 switch(option) {
615 case PHP_STREAM_OPTION_BLOCKING:
616 if (fd == -1)
617 return -1;
618 #ifdef O_NONBLOCK
619 flags = fcntl(fd, F_GETFL, 0);
620 oldval = (flags & O_NONBLOCK) ? 0 : 1;
621 if (value)
622 flags &= ~O_NONBLOCK;
623 else
624 flags |= O_NONBLOCK;
625
626 if (-1 == fcntl(fd, F_SETFL, flags))
627 return -1;
628 return oldval;
629 #else
630 return -1;
631 #endif
632
633 case PHP_STREAM_OPTION_WRITE_BUFFER:
634
635 if (data->file == NULL) {
636 return -1;
637 }
638
639 if (ptrparam)
640 size = *(size_t *)ptrparam;
641 else
642 size = BUFSIZ;
643
644 switch(value) {
645 case PHP_STREAM_BUFFER_NONE:
646 return setvbuf(data->file, NULL, _IONBF, 0);
647
648 case PHP_STREAM_BUFFER_LINE:
649 return setvbuf(data->file, NULL, _IOLBF, size);
650
651 case PHP_STREAM_BUFFER_FULL:
652 return setvbuf(data->file, NULL, _IOFBF, size);
653
654 default:
655 return -1;
656 }
657 break;
658
659 case PHP_STREAM_OPTION_LOCKING:
660 if (fd == -1) {
661 return -1;
662 }
663
664 if ((zend_uintptr_t) ptrparam == PHP_STREAM_LOCK_SUPPORTED) {
665 return 0;
666 }
667
668 if (!flock(fd, value)) {
669 data->lock_flag = value;
670 return 0;
671 } else {
672 return -1;
673 }
674 break;
675
676 case PHP_STREAM_OPTION_MMAP_API:
677 #if HAVE_MMAP
678 {
679 php_stream_mmap_range *range = (php_stream_mmap_range*)ptrparam;
680 int prot, flags;
681
682 switch (value) {
683 case PHP_STREAM_MMAP_SUPPORTED:
684 return fd == -1 ? PHP_STREAM_OPTION_RETURN_ERR : PHP_STREAM_OPTION_RETURN_OK;
685
686 case PHP_STREAM_MMAP_MAP_RANGE:
687 if(do_fstat(data, 1) != 0) {
688 return PHP_STREAM_OPTION_RETURN_ERR;
689 }
690 if (range->length == 0 && range->offset > 0 && range->offset < data->sb.st_size) {
691 range->length = data->sb.st_size - range->offset;
692 }
693 if (range->length == 0 || range->length > data->sb.st_size) {
694 range->length = data->sb.st_size;
695 }
696 if (range->offset >= data->sb.st_size) {
697 range->offset = data->sb.st_size;
698 range->length = 0;
699 }
700 switch (range->mode) {
701 case PHP_STREAM_MAP_MODE_READONLY:
702 prot = PROT_READ;
703 flags = MAP_PRIVATE;
704 break;
705 case PHP_STREAM_MAP_MODE_READWRITE:
706 prot = PROT_READ | PROT_WRITE;
707 flags = MAP_PRIVATE;
708 break;
709 case PHP_STREAM_MAP_MODE_SHARED_READONLY:
710 prot = PROT_READ;
711 flags = MAP_SHARED;
712 break;
713 case PHP_STREAM_MAP_MODE_SHARED_READWRITE:
714 prot = PROT_READ | PROT_WRITE;
715 flags = MAP_SHARED;
716 break;
717 default:
718 return PHP_STREAM_OPTION_RETURN_ERR;
719 }
720 range->mapped = (char*)mmap(NULL, range->length, prot, flags, fd, range->offset);
721 if (range->mapped == (char*)MAP_FAILED) {
722 range->mapped = NULL;
723 return PHP_STREAM_OPTION_RETURN_ERR;
724 }
725
726 data->last_mapped_addr = range->mapped;
727 data->last_mapped_len = range->length;
728 return PHP_STREAM_OPTION_RETURN_OK;
729
730 case PHP_STREAM_MMAP_UNMAP:
731 if (data->last_mapped_addr) {
732 munmap(data->last_mapped_addr, data->last_mapped_len);
733 data->last_mapped_addr = NULL;
734
735 return PHP_STREAM_OPTION_RETURN_OK;
736 }
737 return PHP_STREAM_OPTION_RETURN_ERR;
738 }
739 }
740 #elif defined(PHP_WIN32)
741 {
742 php_stream_mmap_range *range = (php_stream_mmap_range*)ptrparam;
743 HANDLE hfile = (HANDLE)_get_osfhandle(fd);
744 DWORD prot, acc, loffs = 0, delta = 0;
745
746 switch (value) {
747 case PHP_STREAM_MMAP_SUPPORTED:
748 return hfile == INVALID_HANDLE_VALUE ? PHP_STREAM_OPTION_RETURN_ERR : PHP_STREAM_OPTION_RETURN_OK;
749
750 case PHP_STREAM_MMAP_MAP_RANGE:
751 switch (range->mode) {
752 case PHP_STREAM_MAP_MODE_READONLY:
753 prot = PAGE_READONLY;
754 acc = FILE_MAP_READ;
755 break;
756 case PHP_STREAM_MAP_MODE_READWRITE:
757 prot = PAGE_READWRITE;
758 acc = FILE_MAP_READ | FILE_MAP_WRITE;
759 break;
760 case PHP_STREAM_MAP_MODE_SHARED_READONLY:
761 prot = PAGE_READONLY;
762 acc = FILE_MAP_READ;
763
764 break;
765 case PHP_STREAM_MAP_MODE_SHARED_READWRITE:
766 prot = PAGE_READWRITE;
767 acc = FILE_MAP_READ | FILE_MAP_WRITE;
768
769 break;
770 default:
771 return PHP_STREAM_OPTION_RETURN_ERR;
772 }
773
774
775 data->file_mapping = CreateFileMapping(hfile, NULL, prot, 0, 0, NULL);
776
777 if (data->file_mapping == NULL) {
778 return PHP_STREAM_OPTION_RETURN_ERR;
779 }
780
781 size = GetFileSize(hfile, NULL);
782 if (range->length == 0 && range->offset > 0 && range->offset < size) {
783 range->length = size - range->offset;
784 }
785 if (range->length == 0 || range->length > size) {
786 range->length = size;
787 }
788 if (range->offset >= size) {
789 range->offset = size;
790 range->length = 0;
791 }
792
793
794 if (range->offset != 0) {
795 SYSTEM_INFO info;
796 DWORD gran;
797
798 GetSystemInfo(&info);
799 gran = info.dwAllocationGranularity;
800 loffs = ((DWORD)range->offset / gran) * gran;
801 delta = (DWORD)range->offset - loffs;
802 }
803
804 data->last_mapped_addr = MapViewOfFile(data->file_mapping, acc, 0, loffs, range->length + delta);
805
806 if (data->last_mapped_addr) {
807
808 range->mapped = data->last_mapped_addr + delta;
809 return PHP_STREAM_OPTION_RETURN_OK;
810 }
811
812 CloseHandle(data->file_mapping);
813 data->file_mapping = NULL;
814
815 return PHP_STREAM_OPTION_RETURN_ERR;
816
817 case PHP_STREAM_MMAP_UNMAP:
818 if (data->last_mapped_addr) {
819 UnmapViewOfFile(data->last_mapped_addr);
820 data->last_mapped_addr = NULL;
821 CloseHandle(data->file_mapping);
822 data->file_mapping = NULL;
823 return PHP_STREAM_OPTION_RETURN_OK;
824 }
825 return PHP_STREAM_OPTION_RETURN_ERR;
826
827 default:
828 return PHP_STREAM_OPTION_RETURN_ERR;
829 }
830 }
831
832 #endif
833 return PHP_STREAM_OPTION_RETURN_NOTIMPL;
834
835 case PHP_STREAM_OPTION_TRUNCATE_API:
836 switch (value) {
837 case PHP_STREAM_TRUNCATE_SUPPORTED:
838 return fd == -1 ? PHP_STREAM_OPTION_RETURN_ERR : PHP_STREAM_OPTION_RETURN_OK;
839
840 case PHP_STREAM_TRUNCATE_SET_SIZE: {
841 ptrdiff_t new_size = *(ptrdiff_t*)ptrparam;
842 if (new_size < 0) {
843 return PHP_STREAM_OPTION_RETURN_ERR;
844 }
845 return ftruncate(fd, new_size) == 0 ? PHP_STREAM_OPTION_RETURN_OK : PHP_STREAM_OPTION_RETURN_ERR;
846 }
847 }
848
849 #ifdef PHP_WIN32
850 case PHP_STREAM_OPTION_PIPE_BLOCKING:
851 data->is_pipe_blocking = value;
852 return PHP_STREAM_OPTION_RETURN_OK;
853 #endif
854
855 default:
856 return PHP_STREAM_OPTION_RETURN_NOTIMPL;
857 }
858 }
859
860 PHPAPI php_stream_ops php_stream_stdio_ops = {
861 php_stdiop_write, php_stdiop_read,
862 php_stdiop_close, php_stdiop_flush,
863 "STDIO",
864 php_stdiop_seek,
865 php_stdiop_cast,
866 php_stdiop_stat,
867 php_stdiop_set_option
868 };
869
870
871
872 static size_t php_plain_files_dirstream_read(php_stream *stream, char *buf, size_t count)
873 {
874 DIR *dir = (DIR*)stream->abstract;
875
876 char entry[sizeof(struct dirent)+MAXPATHLEN];
877 struct dirent *result = (struct dirent *)&entry;
878 php_stream_dirent *ent = (php_stream_dirent*)buf;
879
880
881 if (count != sizeof(php_stream_dirent))
882 return 0;
883
884 if (php_readdir_r(dir, (struct dirent *)entry, &result) == 0 && result) {
885 PHP_STRLCPY(ent->d_name, result->d_name, sizeof(ent->d_name), strlen(result->d_name));
886 return sizeof(php_stream_dirent);
887 }
888 return 0;
889 }
890
891 static int php_plain_files_dirstream_close(php_stream *stream, int close_handle)
892 {
893 return closedir((DIR *)stream->abstract);
894 }
895
896 static int php_plain_files_dirstream_rewind(php_stream *stream, zend_off_t offset, int whence, zend_off_t *newoffs)
897 {
898 rewinddir((DIR *)stream->abstract);
899 return 0;
900 }
901
902 static php_stream_ops php_plain_files_dirstream_ops = {
903 NULL, php_plain_files_dirstream_read,
904 php_plain_files_dirstream_close, NULL,
905 "dir",
906 php_plain_files_dirstream_rewind,
907 NULL,
908 NULL,
909 NULL
910 };
911
912 static php_stream *php_plain_files_dir_opener(php_stream_wrapper *wrapper, const char *path, const char *mode,
913 int options, zend_string **opened_path, php_stream_context *context STREAMS_DC)
914 {
915 DIR *dir = NULL;
916 php_stream *stream = NULL;
917
918 #ifdef HAVE_GLOB
919 if (options & STREAM_USE_GLOB_DIR_OPEN) {
920 return php_glob_stream_wrapper.wops->dir_opener(&php_glob_stream_wrapper, path, mode, options, opened_path, context STREAMS_REL_CC);
921 }
922 #endif
923
924 if (((options & STREAM_DISABLE_OPEN_BASEDIR) == 0) && php_check_open_basedir(path)) {
925 return NULL;
926 }
927
928 dir = VCWD_OPENDIR(path);
929
930 #ifdef PHP_WIN32
931 if (!dir) {
932 php_win32_docref2_from_error(GetLastError(), path, path);
933 }
934
935 if (dir && dir->finished) {
936 closedir(dir);
937 dir = NULL;
938 }
939 #endif
940 if (dir) {
941 stream = php_stream_alloc(&php_plain_files_dirstream_ops, dir, 0, mode);
942 if (stream == NULL)
943 closedir(dir);
944 }
945
946 return stream;
947 }
948
949
950
951 PHPAPI php_stream *_php_stream_fopen(const char *filename, const char *mode, zend_string **opened_path, int options STREAMS_DC)
952 {
953 char realpath[MAXPATHLEN];
954 int open_flags;
955 int fd;
956 php_stream *ret;
957 int persistent = options & STREAM_OPEN_PERSISTENT;
958 char *persistent_id = NULL;
959
960 if (FAILURE == php_stream_parse_fopen_modes(mode, &open_flags)) {
961 if (options & REPORT_ERRORS) {
962 php_error_docref(NULL, E_WARNING, "`%s' is not a valid mode for fopen", mode);
963 }
964 return NULL;
965 }
966
967 if (options & STREAM_ASSUME_REALPATH) {
968 strlcpy(realpath, filename, sizeof(realpath));
969 } else {
970 if (expand_filepath(filename, realpath) == NULL) {
971 return NULL;
972 }
973 }
974
975 if (persistent) {
976 spprintf(&persistent_id, 0, "streams_stdio_%d_%s", open_flags, realpath);
977 switch (php_stream_from_persistent_id(persistent_id, &ret)) {
978 case PHP_STREAM_PERSISTENT_SUCCESS:
979 if (opened_path) {
980
981 *opened_path = zend_string_init(realpath, strlen(realpath), 0);
982 }
983
984
985 case PHP_STREAM_PERSISTENT_FAILURE:
986 efree(persistent_id);;
987 return ret;
988 }
989 }
990
991 fd = open(realpath, open_flags, 0666);
992
993 if (fd != -1) {
994
995 if (options & STREAM_OPEN_FOR_INCLUDE) {
996 ret = php_stream_fopen_from_fd_int_rel(fd, mode, persistent_id);
997 } else {
998 ret = php_stream_fopen_from_fd_rel(fd, mode, persistent_id);
999 }
1000
1001 if (ret) {
1002 if (opened_path) {
1003 *opened_path = zend_string_init(realpath, strlen(realpath), 0);
1004 }
1005 if (persistent_id) {
1006 efree(persistent_id);
1007 }
1008
1009
1010 #ifndef PHP_WIN32
1011
1012
1013
1014 if (options & STREAM_OPEN_FOR_INCLUDE) {
1015 php_stdio_stream_data *self = (php_stdio_stream_data*)ret->abstract;
1016 int r;
1017
1018 r = do_fstat(self, 0);
1019 if ((r == 0 && !S_ISREG(self->sb.st_mode))) {
1020 if (opened_path) {
1021 zend_string_release(*opened_path);
1022 *opened_path = NULL;
1023 }
1024 php_stream_close(ret);
1025 return NULL;
1026 }
1027 }
1028
1029 if (options & STREAM_USE_BLOCKING_PIPE) {
1030 php_stdio_stream_data *self = (php_stdio_stream_data*)ret->abstract;
1031 self->is_pipe_blocking = 1;
1032 }
1033 #endif
1034
1035 return ret;
1036 }
1037 close(fd);
1038 }
1039 if (persistent_id) {
1040 efree(persistent_id);
1041 }
1042 return NULL;
1043 }
1044
1045
1046
1047 static php_stream *php_plain_files_stream_opener(php_stream_wrapper *wrapper, const char *path, const char *mode,
1048 int options, zend_string **opened_path, php_stream_context *context STREAMS_DC)
1049 {
1050 if (((options & STREAM_DISABLE_OPEN_BASEDIR) == 0) && php_check_open_basedir(path)) {
1051 return NULL;
1052 }
1053
1054 return php_stream_fopen_rel(path, mode, opened_path, options);
1055 }
1056
1057 static int php_plain_files_url_stater(php_stream_wrapper *wrapper, const char *url, int flags, php_stream_statbuf *ssb, php_stream_context *context)
1058 {
1059 if (strncasecmp(url, "file://", sizeof("file://") - 1) == 0) {
1060 url += sizeof("file://") - 1;
1061 }
1062
1063 if (php_check_open_basedir_ex(url, (flags & PHP_STREAM_URL_STAT_QUIET) ? 0 : 1)) {
1064 return -1;
1065 }
1066
1067 #ifdef PHP_WIN32
1068 if (flags & PHP_STREAM_URL_STAT_LINK) {
1069 return VCWD_LSTAT(url, &ssb->sb);
1070 }
1071 #else
1072 # ifdef HAVE_SYMLINK
1073 if (flags & PHP_STREAM_URL_STAT_LINK) {
1074 return VCWD_LSTAT(url, &ssb->sb);
1075 } else
1076 # endif
1077 #endif
1078 return VCWD_STAT(url, &ssb->sb);
1079 }
1080
1081 static int php_plain_files_unlink(php_stream_wrapper *wrapper, const char *url, int options, php_stream_context *context)
1082 {
1083 int ret;
1084
1085 if (strncasecmp(url, "file://", sizeof("file://") - 1) == 0) {
1086 url += sizeof("file://") - 1;
1087 }
1088
1089 if (php_check_open_basedir(url)) {
1090 return 0;
1091 }
1092
1093 ret = VCWD_UNLINK(url);
1094 if (ret == -1) {
1095 if (options & REPORT_ERRORS) {
1096 php_error_docref1(NULL, url, E_WARNING, "%s", strerror(errno));
1097 }
1098 return 0;
1099 }
1100
1101
1102 php_clear_stat_cache(1, NULL, 0);
1103
1104 return 1;
1105 }
1106
1107 static int php_plain_files_rename(php_stream_wrapper *wrapper, const char *url_from, const char *url_to, int options, php_stream_context *context)
1108 {
1109 int ret;
1110
1111 if (!url_from || !url_to) {
1112 return 0;
1113 }
1114
1115 #ifdef PHP_WIN32
1116 if (!php_win32_check_trailing_space(url_from, (int)strlen(url_from))) {
1117 php_win32_docref2_from_error(ERROR_INVALID_NAME, url_from, url_to);
1118 return 0;
1119 }
1120 if (!php_win32_check_trailing_space(url_to, (int)strlen(url_to))) {
1121 php_win32_docref2_from_error(ERROR_INVALID_NAME, url_from, url_to);
1122 return 0;
1123 }
1124 #endif
1125
1126 if (strncasecmp(url_from, "file://", sizeof("file://") - 1) == 0) {
1127 url_from += sizeof("file://") - 1;
1128 }
1129
1130 if (strncasecmp(url_to, "file://", sizeof("file://") - 1) == 0) {
1131 url_to += sizeof("file://") - 1;
1132 }
1133
1134 if (php_check_open_basedir(url_from) || php_check_open_basedir(url_to)) {
1135 return 0;
1136 }
1137
1138 ret = VCWD_RENAME(url_from, url_to);
1139
1140 if (ret == -1) {
1141 #ifndef PHP_WIN32
1142 # ifdef EXDEV
1143 if (errno == EXDEV) {
1144 zend_stat_t sb;
1145 if (php_copy_file(url_from, url_to) == SUCCESS) {
1146 if (VCWD_STAT(url_from, &sb) == 0) {
1147 # if !defined(TSRM_WIN32) && !defined(NETWARE)
1148 if (VCWD_CHMOD(url_to, sb.st_mode)) {
1149 if (errno == EPERM) {
1150 php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s", strerror(errno));
1151 VCWD_UNLINK(url_from);
1152 return 1;
1153 }
1154 php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s", strerror(errno));
1155 return 0;
1156 }
1157 if (VCWD_CHOWN(url_to, sb.st_uid, sb.st_gid)) {
1158 if (errno == EPERM) {
1159 php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s", strerror(errno));
1160 VCWD_UNLINK(url_from);
1161 return 1;
1162 }
1163 php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s", strerror(errno));
1164 return 0;
1165 }
1166 # endif
1167 VCWD_UNLINK(url_from);
1168 return 1;
1169 }
1170 }
1171 php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s", strerror(errno));
1172 return 0;
1173 }
1174 # endif
1175 #endif
1176
1177 #ifdef PHP_WIN32
1178 php_win32_docref2_from_error(GetLastError(), url_from, url_to);
1179 #else
1180 php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s", strerror(errno));
1181 #endif
1182 return 0;
1183 }
1184
1185
1186 php_clear_stat_cache(1, NULL, 0);
1187
1188 return 1;
1189 }
1190
1191 static int php_plain_files_mkdir(php_stream_wrapper *wrapper, const char *dir, int mode, int options, php_stream_context *context)
1192 {
1193 int ret, recursive = options & PHP_STREAM_MKDIR_RECURSIVE;
1194 char *p;
1195
1196 if (strncasecmp(dir, "file://", sizeof("file://") - 1) == 0) {
1197 dir += sizeof("file://") - 1;
1198 }
1199
1200 if (!recursive) {
1201 ret = php_mkdir(dir, mode);
1202 } else {
1203
1204 char *e;
1205 zend_stat_t sb;
1206 int dir_len = (int)strlen(dir);
1207 int offset = 0;
1208 char buf[MAXPATHLEN];
1209
1210 if (!expand_filepath_with_mode(dir, buf, NULL, 0, CWD_EXPAND )) {
1211 php_error_docref(NULL, E_WARNING, "Invalid path");
1212 return 0;
1213 }
1214
1215 e = buf + strlen(buf);
1216
1217 if ((p = memchr(buf, DEFAULT_SLASH, dir_len))) {
1218 offset = p - buf + 1;
1219 }
1220
1221 if (p && dir_len == 1) {
1222
1223 }
1224 else {
1225
1226 while ( (p = strrchr(buf + offset, DEFAULT_SLASH)) || (offset != 1 && (p = strrchr(buf, DEFAULT_SLASH))) ) {
1227 int n = 0;
1228
1229 *p = '\0';
1230 while (p > buf && *(p-1) == DEFAULT_SLASH) {
1231 ++n;
1232 --p;
1233 *p = '\0';
1234 }
1235 if (VCWD_STAT(buf, &sb) == 0) {
1236 while (1) {
1237 *p = DEFAULT_SLASH;
1238 if (!n) break;
1239 --n;
1240 ++p;
1241 }
1242 break;
1243 }
1244 }
1245 }
1246
1247 if (p == buf) {
1248 ret = php_mkdir(dir, mode);
1249 } else if (!(ret = php_mkdir(buf, mode))) {
1250 if (!p) {
1251 p = buf;
1252 }
1253
1254 while (++p != e) {
1255 if (*p == '\0') {
1256 *p = DEFAULT_SLASH;
1257 if ((*(p+1) != '\0') &&
1258 (ret = VCWD_MKDIR(buf, (mode_t)mode)) < 0) {
1259 if (options & REPORT_ERRORS) {
1260 php_error_docref(NULL, E_WARNING, "%s", strerror(errno));
1261 }
1262 break;
1263 }
1264 }
1265 }
1266 }
1267 }
1268 if (ret < 0) {
1269
1270 return 0;
1271 } else {
1272
1273 return 1;
1274 }
1275 }
1276
1277 static int php_plain_files_rmdir(php_stream_wrapper *wrapper, const char *url, int options, php_stream_context *context)
1278 {
1279 if (strncasecmp(url, "file://", sizeof("file://") - 1) == 0) {
1280 url += sizeof("file://") - 1;
1281 }
1282
1283 if (php_check_open_basedir(url)) {
1284 return 0;
1285 }
1286
1287 #if PHP_WIN32
1288 if (!php_win32_check_trailing_space(url, (int)strlen(url))) {
1289 php_error_docref1(NULL, url, E_WARNING, "%s", strerror(ENOENT));
1290 return 0;
1291 }
1292 #endif
1293
1294 if (VCWD_RMDIR(url) < 0) {
1295 php_error_docref1(NULL, url, E_WARNING, "%s", strerror(errno));
1296 return 0;
1297 }
1298
1299
1300 php_clear_stat_cache(1, NULL, 0);
1301
1302 return 1;
1303 }
1304
1305 static int php_plain_files_metadata(php_stream_wrapper *wrapper, const char *url, int option, void *value, php_stream_context *context)
1306 {
1307 struct utimbuf *newtime;
1308 #if !defined(WINDOWS) && !defined(NETWARE)
1309 uid_t uid;
1310 gid_t gid;
1311 #endif
1312 mode_t mode;
1313 int ret = 0;
1314 #if PHP_WIN32
1315 int url_len = (int)strlen(url);
1316 #endif
1317
1318 #if PHP_WIN32
1319 if (!php_win32_check_trailing_space(url, url_len)) {
1320 php_error_docref1(NULL, url, E_WARNING, "%s", strerror(ENOENT));
1321 return 0;
1322 }
1323 #endif
1324
1325 if (strncasecmp(url, "file://", sizeof("file://") - 1) == 0) {
1326 url += sizeof("file://") - 1;
1327 }
1328
1329 if (php_check_open_basedir(url)) {
1330 return 0;
1331 }
1332
1333 switch(option) {
1334 case PHP_STREAM_META_TOUCH:
1335 newtime = (struct utimbuf *)value;
1336 if (VCWD_ACCESS(url, F_OK) != 0) {
1337 FILE *file = VCWD_FOPEN(url, "w");
1338 if (file == NULL) {
1339 php_error_docref1(NULL, url, E_WARNING, "Unable to create file %s because %s", url, strerror(errno));
1340 return 0;
1341 }
1342 fclose(file);
1343 }
1344
1345 ret = VCWD_UTIME(url, newtime);
1346 break;
1347 #if !defined(WINDOWS) && !defined(NETWARE)
1348 case PHP_STREAM_META_OWNER_NAME:
1349 case PHP_STREAM_META_OWNER:
1350 if(option == PHP_STREAM_META_OWNER_NAME) {
1351 if(php_get_uid_by_name((char *)value, &uid) != SUCCESS) {
1352 php_error_docref1(NULL, url, E_WARNING, "Unable to find uid for %s", (char *)value);
1353 return 0;
1354 }
1355 } else {
1356 uid = (uid_t)*(long *)value;
1357 }
1358 ret = VCWD_CHOWN(url, uid, -1);
1359 break;
1360 case PHP_STREAM_META_GROUP:
1361 case PHP_STREAM_META_GROUP_NAME:
1362 if(option == PHP_STREAM_META_GROUP_NAME) {
1363 if(php_get_gid_by_name((char *)value, &gid) != SUCCESS) {
1364 php_error_docref1(NULL, url, E_WARNING, "Unable to find gid for %s", (char *)value);
1365 return 0;
1366 }
1367 } else {
1368 gid = (gid_t)*(long *)value;
1369 }
1370 ret = VCWD_CHOWN(url, -1, gid);
1371 break;
1372 #endif
1373 case PHP_STREAM_META_ACCESS:
1374 mode = (mode_t)*(zend_long *)value;
1375 ret = VCWD_CHMOD(url, mode);
1376 break;
1377 default:
1378 php_error_docref1(NULL, url, E_WARNING, "Unknown option %d for stream_metadata", option);
1379 return 0;
1380 }
1381 if (ret == -1) {
1382 php_error_docref1(NULL, url, E_WARNING, "Operation failed: %s", strerror(errno));
1383 return 0;
1384 }
1385 php_clear_stat_cache(0, NULL, 0);
1386 return 1;
1387 }
1388
1389
1390 static php_stream_wrapper_ops php_plain_files_wrapper_ops = {
1391 php_plain_files_stream_opener,
1392 NULL,
1393 NULL,
1394 php_plain_files_url_stater,
1395 php_plain_files_dir_opener,
1396 "plainfile",
1397 php_plain_files_unlink,
1398 php_plain_files_rename,
1399 php_plain_files_mkdir,
1400 php_plain_files_rmdir,
1401 php_plain_files_metadata
1402 };
1403
1404 PHPAPI php_stream_wrapper php_plain_files_wrapper = {
1405 &php_plain_files_wrapper_ops,
1406 NULL,
1407 0
1408 };
1409
1410
1411 PHPAPI php_stream *_php_stream_fopen_with_path(const char *filename, const char *mode, const char *path, zend_string **opened_path, int options STREAMS_DC)
1412 {
1413
1414 char *pathbuf, *end;
1415 const char *ptr;
1416 char trypath[MAXPATHLEN];
1417 php_stream *stream;
1418 int filename_length;
1419 zend_string *exec_filename;
1420
1421 if (opened_path) {
1422 *opened_path = NULL;
1423 }
1424
1425 if(!filename) {
1426 return NULL;
1427 }
1428
1429 filename_length = (int)strlen(filename);
1430 #ifndef PHP_WIN32
1431 (void) filename_length;
1432 #endif
1433
1434
1435 if (*filename == '.' && (IS_SLASH(filename[1]) || filename[1] == '.')) {
1436
1437 ptr = filename + 1;
1438 if (*ptr == '.') {
1439 while (*(++ptr) == '.');
1440 if (!IS_SLASH(*ptr)) {
1441 goto not_relative_path;
1442 }
1443 }
1444
1445
1446 if (((options & STREAM_DISABLE_OPEN_BASEDIR) == 0) && php_check_open_basedir(filename)) {
1447 return NULL;
1448 }
1449
1450 return php_stream_fopen_rel(filename, mode, opened_path, options);
1451 }
1452
1453 not_relative_path:
1454
1455
1456 if (IS_ABSOLUTE_PATH(filename, filename_length)) {
1457
1458 if (((options & STREAM_DISABLE_OPEN_BASEDIR) == 0) && php_check_open_basedir(filename)) {
1459 return NULL;
1460 }
1461
1462 return php_stream_fopen_rel(filename, mode, opened_path, options);
1463 }
1464
1465 #ifdef PHP_WIN32
1466 if (IS_SLASH(filename[0])) {
1467 size_t cwd_len;
1468 char *cwd;
1469 cwd = virtual_getcwd_ex(&cwd_len);
1470
1471 *(cwd+3) = '\0';
1472
1473 if (snprintf(trypath, MAXPATHLEN, "%s%s", cwd, filename) >= MAXPATHLEN) {
1474 php_error_docref(NULL, E_NOTICE, "%s/%s path was truncated to %d", cwd, filename, MAXPATHLEN);
1475 }
1476
1477 efree(cwd);
1478
1479 if (((options & STREAM_DISABLE_OPEN_BASEDIR) == 0) && php_check_open_basedir(trypath)) {
1480 return NULL;
1481 }
1482
1483 return php_stream_fopen_rel(trypath, mode, opened_path, options);
1484 }
1485 #endif
1486
1487 if (!path || (path && !*path)) {
1488 return php_stream_fopen_rel(filename, mode, opened_path, options);
1489 }
1490
1491
1492
1493
1494
1495 if (zend_is_executing() &&
1496 (exec_filename = zend_get_executed_filename_ex()) != NULL) {
1497 const char *exec_fname = ZSTR_VAL(exec_filename);
1498 size_t exec_fname_length = ZSTR_LEN(exec_filename);
1499
1500 while ((--exec_fname_length < SIZE_MAX) && !IS_SLASH(exec_fname[exec_fname_length]));
1501 if (exec_fname_length<=0) {
1502
1503 pathbuf = estrdup(path);
1504 } else {
1505 size_t path_length = strlen(path);
1506
1507 pathbuf = (char *) emalloc(exec_fname_length + path_length +1 +1);
1508 memcpy(pathbuf, path, path_length);
1509 pathbuf[path_length] = DEFAULT_DIR_SEPARATOR;
1510 memcpy(pathbuf+path_length+1, exec_fname, exec_fname_length);
1511 pathbuf[path_length + exec_fname_length +1] = '\0';
1512 }
1513 } else {
1514 pathbuf = estrdup(path);
1515 }
1516
1517 ptr = pathbuf;
1518
1519 while (ptr && *ptr) {
1520 end = strchr(ptr, DEFAULT_DIR_SEPARATOR);
1521 if (end != NULL) {
1522 *end = '\0';
1523 end++;
1524 }
1525 if (*ptr == '\0') {
1526 goto stream_skip;
1527 }
1528 if (snprintf(trypath, MAXPATHLEN, "%s/%s", ptr, filename) >= MAXPATHLEN) {
1529 php_error_docref(NULL, E_NOTICE, "%s/%s path was truncated to %d", ptr, filename, MAXPATHLEN);
1530 }
1531
1532 if (((options & STREAM_DISABLE_OPEN_BASEDIR) == 0) && php_check_open_basedir_ex(trypath, 0)) {
1533 goto stream_skip;
1534 }
1535
1536 stream = php_stream_fopen_rel(trypath, mode, opened_path, options);
1537 if (stream) {
1538 efree(pathbuf);
1539 return stream;
1540 }
1541 stream_skip:
1542 ptr = end;
1543 }
1544
1545 efree(pathbuf);
1546 return NULL;
1547
1548 }
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558