]> granicus.if.org Git - php/commitdiff
MFH: streams fixes
authorWez Furlong <wez@php.net>
Sat, 31 Jul 2004 11:00:11 +0000 (11:00 +0000)
committerWez Furlong <wez@php.net>
Sat, 31 Jul 2004 11:00:11 +0000 (11:00 +0000)
main/streams/plain_wrapper.c
main/streams/transports.c
main/streams/xp_socket.c

index c37f38221cb490318a73a53563a89ee519fa6676..1f48ea4469cb6a151356e3e18a8593b543fb7d66 100644 (file)
@@ -83,93 +83,16 @@ PHPAPI int php_stream_parse_fopen_modes(const char *mode, int *open_flags)
 }
 
 
-/* {{{ php_stream_fopen */
-PHPAPI php_stream *_php_stream_fopen(const char *filename, const char *mode, char **opened_path, int options STREAMS_DC TSRMLS_DC)
-{
-       char *realpath = NULL;
-       struct stat st;
-       int open_flags;
-       int fd;
-       php_stream *ret;
-       int persistent = options & STREAM_OPEN_PERSISTENT;
-       char *persistent_id = NULL;
-
-       if (FAILURE == php_stream_parse_fopen_modes(mode, &open_flags)) {
-               if (options & REPORT_ERRORS) {
-                       php_error_docref(NULL TSRMLS_CC, E_WARNING, "`%s' is not a valid mode for fopen", mode);
-               }
-               return NULL;
-       }
-       
-       if ((realpath = expand_filepath(filename, NULL TSRMLS_CC)) == NULL) {
-               return NULL;
-       }
-
-       if (persistent) {
-               spprintf(&persistent_id, 0, "streams_stdio_%d_%s", open_flags, realpath);
-               switch (php_stream_from_persistent_id(persistent_id, &ret TSRMLS_CC)) {
-                       case PHP_STREAM_PERSISTENT_SUCCESS:
-                               if (opened_path) {
-                                       *opened_path = realpath;
-                                       realpath = NULL;
-                               }
-                               if (realpath) {
-                                       efree(realpath);
-                               }
-                               /* fall through */
-
-                       case PHP_STREAM_PERSISTENT_FAILURE:
-                               efree(persistent_id);;
-                               return ret;
-               }
-       }
-       
-       fd = open(realpath, open_flags, 0666);
-
-       if (fd != -1)   {
-               /* sanity checks for include/require */
-               if (options & STREAM_OPEN_FOR_INCLUDE && (fstat(fd, &st) == -1 || !S_ISREG(st.st_mode))) {
-#ifdef PHP_WIN32
-                       /* skip the sanity check; fstat doesn't appear to work on
-                        * UNC paths */
-                       if (!IS_UNC_PATH(filename, strlen(filename)))
-#endif
-                               goto err;
-               } 
-       
-               ret = php_stream_fopen_from_fd_rel(fd, mode, persistent_id);
-
-               if (ret)        {
-                       if (opened_path) {
-                               *opened_path = realpath;
-                               realpath = NULL;
-                       }
-                       if (realpath) {
-                               efree(realpath);
-                       }
-                       if (persistent_id) {
-                               efree(persistent_id);
-                       }
-                       return ret;
-               }
-err:
-               close(fd);
-       }
-       efree(realpath);
-       if (persistent_id) {
-               efree(persistent_id);
-       }
-       return NULL;
-}
-/* }}} */
-
 /* {{{ ------- STDIO stream implementation -------*/
 
 typedef struct {
        FILE *file;
        int fd;                                 /* underlying file descriptor */
-       int is_process_pipe;    /* use pclose instead of fclose */
-       int is_pipe;                    /* don't try and seek */
+       unsigned is_process_pipe:1;     /* use pclose instead of fclose */
+       unsigned is_pipe:1;                     /* don't try and seek */
+       unsigned cached_fstat:1;        /* sb is valid */
+       unsigned _reserved:29;
+       
        int lock_flag;                  /* stores the lock state */
        char *temp_file_name;   /* if non-null, this is the path to a temporary file that
                                                         * is to be deleted when the stream is closed */
@@ -185,7 +108,25 @@ typedef struct {
        char *last_mapped_addr;
        HANDLE file_mapping;
 #endif
+
+       struct stat sb;
 } php_stdio_stream_data;
+#define PHP_STDIOP_GET_FD(anfd, data)  anfd = (data)->file ? fileno((data)->file) : (data)->fd
+
+static int do_fstat(php_stdio_stream_data *d, int force)
+{
+       if (!d->cached_fstat || force) {
+               int fd;
+               int r;
+          
+               PHP_STDIOP_GET_FD(fd, d);
+               r = fstat(fd, &d->sb);
+               d->cached_fstat = r == 0;
+
+               return r;
+       }
+       return 0;
+}
 
 PHPAPI php_stream *_php_stream_fopen_temporary_file(const char *dir, const char *pfx, char **opened_path STREAMS_DC TSRMLS_DC)
 {
@@ -246,8 +187,7 @@ PHPAPI php_stream *_php_stream_fopen_from_fd(int fd, const char *mode, const cha
 #ifdef S_ISFIFO
        /* detect if this is a pipe */
        if (self->fd >= 0) {
-               struct stat sb;
-               self->is_pipe = (fstat(self->fd, &sb) == 0 && S_ISFIFO(sb.st_mode)) ? 1 : 0;
+               self->is_pipe = (do_fstat(self, 0) == 0 && S_ISFIFO(self->sb.st_mode)) ? 1 : 0;
        }
 #elif defined(PHP_WIN32)
        {
@@ -290,8 +230,7 @@ PHPAPI php_stream *_php_stream_fopen_from_file(FILE *file, const char *mode STRE
 #ifdef S_ISFIFO
        /* detect if this is a pipe */
        if (self->fd >= 0) {
-               struct stat sb;
-               self->is_pipe = (fstat(self->fd, &sb) == 0 && S_ISFIFO(sb.st_mode)) ? 1 : 0;
+               self->is_pipe = (do_fstat(self, 0) == 0 && S_ISFIFO(self->sb.st_mode)) ? 1 : 0;
        }
 #elif defined(PHP_WIN32)
        {
@@ -336,8 +275,6 @@ PHPAPI php_stream *_php_stream_fopen_from_pipe(FILE *file, const char *mode STRE
        return stream;
 }
 
-#define PHP_STDIOP_GET_FD(anfd, data)  anfd = (data)->file ? fileno((data)->file) : (data)->fd
-
 static size_t php_stdiop_write(php_stream *stream, const char *buf, size_t count TSRMLS_DC)
 {
        php_stdio_stream_data *data = (php_stdio_stream_data*)stream->abstract;
@@ -561,14 +498,14 @@ static int php_stdiop_cast(php_stream *stream, int castas, void **ret TSRMLS_DC)
 
 static int php_stdiop_stat(php_stream *stream, php_stream_statbuf *ssb TSRMLS_DC)
 {
-       int fd;
+       int ret;
        php_stdio_stream_data *data = (php_stdio_stream_data*) stream->abstract;
 
        assert(data != NULL);
 
-       PHP_STDIOP_GET_FD(fd, data);
-       
-       return fstat(fd, &ssb->sb);
+       ret = do_fstat(data, 1);
+       memcpy(&ssb->sb, &data->sb, sizeof(ssb->sb));
+       return ret;
 }
 
 static int php_stdiop_set_option(php_stream *stream, int option, int value, void *ptrparam TSRMLS_DC)
@@ -653,7 +590,6 @@ static int php_stdiop_set_option(php_stream *stream, int option, int value, void
 #if HAVE_MMAP
                        {
                                php_stream_mmap_range *range = (php_stream_mmap_range*)ptrparam;
-                               struct stat sbuf;
                                int prot, flags;
                                
                                switch (value) {
@@ -661,9 +597,9 @@ static int php_stdiop_set_option(php_stream *stream, int option, int value, void
                                                return fd == -1 ? PHP_STREAM_OPTION_RETURN_ERR : PHP_STREAM_OPTION_RETURN_OK;
 
                                        case PHP_STREAM_MMAP_MAP_RANGE:
-                                               fstat(fd, &sbuf);
-                                               if (range->length == 0 || range->length > sbuf.st_size) {
-                                                       range->length = sbuf.st_size;
+                                               do_fstat(data, 1);
+                                               if (range->length == 0 || range->length > data->sb.st_size) {
+                                                       range->length = data->sb.st_size;
                                                }
                                                switch (range->mode) {
                                                        case PHP_STREAM_MAP_MODE_READONLY:
@@ -888,6 +824,94 @@ static php_stream *php_plain_files_dir_opener(php_stream_wrapper *wrapper, char
 }
 /* }}} */
 
+/* {{{ php_stream_fopen */
+PHPAPI php_stream *_php_stream_fopen(const char *filename, const char *mode, char **opened_path, int options STREAMS_DC TSRMLS_DC)
+{
+       char *realpath = NULL;
+       int open_flags;
+       int fd;
+       php_stream *ret;
+       int persistent = options & STREAM_OPEN_PERSISTENT;
+       char *persistent_id = NULL;
+
+       if (FAILURE == php_stream_parse_fopen_modes(mode, &open_flags)) {
+               if (options & REPORT_ERRORS) {
+                       php_error_docref(NULL TSRMLS_CC, E_WARNING, "`%s' is not a valid mode for fopen", mode);
+               }
+               return NULL;
+       }
+       
+       if ((realpath = expand_filepath(filename, NULL TSRMLS_CC)) == NULL) {
+               return NULL;
+       }
+
+       if (persistent) {
+               spprintf(&persistent_id, 0, "streams_stdio_%d_%s", open_flags, realpath);
+               switch (php_stream_from_persistent_id(persistent_id, &ret TSRMLS_CC)) {
+                       case PHP_STREAM_PERSISTENT_SUCCESS:
+                               if (opened_path) {
+                                       *opened_path = realpath;
+                                       realpath = NULL;
+                               }
+                               if (realpath) {
+                                       efree(realpath);
+                               }
+                               /* fall through */
+
+                       case PHP_STREAM_PERSISTENT_FAILURE:
+                               efree(persistent_id);;
+                               return ret;
+               }
+       }
+       
+       fd = open(realpath, open_flags, 0666);
+
+       if (fd != -1)   {
+
+               ret = php_stream_fopen_from_fd_rel(fd, mode, persistent_id);
+
+               if (ret)        {
+                       if (opened_path) {
+                               *opened_path = realpath;
+                               realpath = NULL;
+                       }
+                       if (realpath) {
+                               efree(realpath);
+                       }
+                       if (persistent_id) {
+                               efree(persistent_id);
+                       }
+
+                       /* sanity checks for include/require.
+                        * We check these after opening the stream, so that we save
+                        * on fstat() syscalls */
+                       if (options & STREAM_OPEN_FOR_INCLUDE) {
+                               php_stdio_stream_data *self = (php_stdio_stream_data*)ret->abstract;
+                               int r;
+
+                               r = do_fstat(self, 0);
+                               if (
+#ifndef PHP_WIN32
+                                               (r != 0) || /* it is OK for fstat to fail under win32 */
+#endif
+                                               (r == 0 && !S_ISREG(self->sb.st_mode))) {
+                                       php_stream_close(ret);
+                                       return NULL;
+                               }
+                       }
+
+                       return ret;
+               }
+               close(fd);
+       }
+       efree(realpath);
+       if (persistent_id) {
+               efree(persistent_id);
+       }
+       return NULL;
+}
+/* }}} */
+
 
 static php_stream *php_plain_files_stream_opener(php_stream_wrapper *wrapper, char *path, char *mode,
                int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC)
index 04a4eccfbd3baefdc02b65cadcaef22804e0c616..37e0757a5e5dafeb797e91507fcb4181f5f08904 100644 (file)
@@ -385,6 +385,7 @@ PHPAPI int php_stream_xport_recvfrom(php_stream *stream, char *buf, size_t bufle
        php_stream_xport_param param;
        int ret = 0;
        int recvd_len = 0;
+#if 0
        int oob;
 
        if (flags == 0 && addr == NULL) {
@@ -416,6 +417,7 @@ PHPAPI int php_stream_xport_recvfrom(php_stream *stream, char *buf, size_t bufle
                        return recvd_len;
                }
        }
+#endif
 
        /* otherwise, we are going to bypass the buffer */
        
@@ -453,9 +455,11 @@ PHPAPI int php_stream_xport_sendto(php_stream *stream, const char *buf, size_t b
        int ret = 0;
        int oob;
 
+#if 0
        if (flags == 0 && addr == NULL) {
                return php_stream_write(stream, buf, buflen);
        }
+#endif
        
        oob = (flags & STREAM_OOB) == STREAM_OOB;
 
index d6fb72257e1f57c3203ed2c2cf76d0eeea52766c..a669c7a2a0bc8f1138de6db678681e7fb53dfabd 100644 (file)
@@ -185,8 +185,11 @@ static int php_sockop_close(php_stream *stream, int close_handle TSRMLS_DC)
 
 static int php_sockop_flush(php_stream *stream TSRMLS_DC)
 {
+#if 0
        php_netstream_data_t *sock = (php_netstream_data_t*)stream->abstract;
        return fsync(sock->socket);
+#endif
+       return 0;
 }
 
 static int php_sockop_stat(php_stream *stream, php_stream_statbuf *ssb TSRMLS_DC)
@@ -195,6 +198,16 @@ static int php_sockop_stat(php_stream *stream, php_stream_statbuf *ssb TSRMLS_DC
        return fstat(sock->socket, &ssb->sb);
 }
 
+static inline int sock_sendto(php_netstream_data_t *sock, char *buf, size_t buflen, int flags,
+               struct sockaddr *addr, socklen_t addrlen
+               TSRMLS_DC)
+{
+       if (addr) {
+               return sendto(sock->socket, buf, buflen, flags, addr, addrlen);
+       }
+       return send(sock->socket, buf, buflen, flags);
+}
+
 static inline int sock_recvfrom(php_netstream_data_t *sock, char *buf, size_t buflen, int flags,
                char **textaddr, long *textaddrlen,
                struct sockaddr **addr, socklen_t *addrlen
@@ -233,11 +246,13 @@ static int php_sockop_set_option(php_stream *stream, int option, int value, void
                                if (value == -1) {
                                        if (sock->timeout.tv_sec == -1) {
                                                tv.tv_sec = FG(default_socket_timeout);
+                                               tv.tv_usec = 0;
                                        } else {
                                                tv = sock->timeout;
                                        }
                                } else {
                                        tv.tv_sec = value;
+                                       tv.tv_usec = 0;
                                }
 
                                if (sock->socket == -1) {
@@ -312,7 +327,7 @@ static int php_sockop_set_option(php_stream *stream, int option, int value, void
                                        if ((xparam->inputs.flags & STREAM_OOB) == STREAM_OOB) {
                                                flags |= MSG_OOB;
                                        }
-                                       xparam->outputs.returncode = sendto(sock->socket,
+                                       xparam->outputs.returncode = sock_sendto(sock,
                                                        xparam->inputs.buf, xparam->inputs.buflen,
                                                        flags,
                                                        xparam->inputs.addr,