diff options
author | Sara Golemon <pollita@php.net> | 2003-11-28 23:25:28 +0000 |
---|---|---|
committer | Sara Golemon <pollita@php.net> | 2003-11-28 23:25:28 +0000 |
commit | 026d4c9e4cec8cb3f03c311b90f05241f2d70455 (patch) | |
tree | e563b6f3699eb94168362c8f00fb1c4d80506e7a | |
parent | 6d86bb9e40386e4127af4f55b8e8e79864255ca1 (diff) | |
download | php-git-026d4c9e4cec8cb3f03c311b90f05241f2d70455.tar.gz |
Route php_stat() via streams/url_stat API (php_stream_stat_path).
This enables fopen-wrappers support on stat() and related family calls.
-rw-r--r-- | NEWS | 1 | ||||
-rw-r--r-- | ext/libxml/libxml.c | 2 | ||||
-rw-r--r-- | ext/standard/basic_functions.h | 8 | ||||
-rw-r--r-- | ext/standard/filestat.c | 146 | ||||
-rw-r--r-- | ext/standard/ftp_fopen_wrapper.c | 4 | ||||
-rwxr-xr-x | main/php_streams.h | 10 | ||||
-rw-r--r-- | main/streams/plain_wrapper.c | 9 | ||||
-rwxr-xr-x | main/streams/streams.c | 35 |
8 files changed, 108 insertions, 107 deletions
@@ -8,6 +8,7 @@ PHP NEWS . php_strip_whitespace(). strip whitespace & comments from a script. (Ilia) . php_check_syntax(). check php script for parse errors. (Ilia) . image_type_to_extension(). return extension based on image type. (Ilia) +- Route stat() and family via streams API. (Sara) - Fixed __autoload() to preserve case of the passed class name. (Andi) - Fixed bug #26072 (--disable-libxml does not work). (Jani) - Fixed bug #26083 (Non-working write support in ext/dom). (Ilia) diff --git a/ext/libxml/libxml.c b/ext/libxml/libxml.c index 0e937df777..49500d88aa 100644 --- a/ext/libxml/libxml.c +++ b/ext/libxml/libxml.c @@ -253,7 +253,7 @@ void *php_libxml_streams_IO_open_wrapper(const char *filename, const char *mode) in xml processing (eg. DTD files) */ wrapper = php_stream_locate_url_wrapper(resolved_path, &path_to_open, ENFORCE_SAFE_MODE TSRMLS_CC); if (wrapper && wrapper->wops->url_stat) { - if (wrapper->wops->url_stat(wrapper, path_to_open, &ssbuf TSRMLS_CC) == -1) { + if (wrapper->wops->url_stat(wrapper, path_to_open, 0, &ssbuf, NULL TSRMLS_CC) == -1) { return NULL; } } diff --git a/ext/standard/basic_functions.h b/ext/standard/basic_functions.h index 86b3729dbe..d6542b85c5 100644 --- a/ext/standard/basic_functions.h +++ b/ext/standard/basic_functions.h @@ -170,11 +170,9 @@ typedef struct _php_basic_globals { long page_inode; long page_mtime; - /* filestat.c */ - char *CurrentStatFile; - php_stat_len CurrentStatLength; - struct stat sb; - struct stat lsb; + /* filestat.c && main/streams/streams.c */ + char *CurrentStatFile, *CurrentLStatFile; + php_stream_statbuf *ssb, *lssb; /* rand.c */ php_uint32 state[MT_N+1]; /* state vector + 1 extra to not violate ANSI C */ diff --git a/ext/standard/filestat.c b/ext/standard/filestat.c index 23e569edca..a111e0ebab 100644 --- a/ext/standard/filestat.c +++ b/ext/standard/filestat.c @@ -99,7 +99,7 @@ PHP_RINIT_FUNCTION(filestat) { BG(CurrentStatFile)=NULL; - BG(CurrentStatLength)=0; + BG(CurrentLStatFile)=NULL; return SUCCESS; } @@ -108,6 +108,9 @@ PHP_RSHUTDOWN_FUNCTION(filestat) if (BG(CurrentStatFile)) { efree (BG(CurrentStatFile)); } + if (BG(CurrentLStatFile)) { + efree (BG(CurrentLStatFile)); + } return SUCCESS; } @@ -526,11 +529,16 @@ PHP_FUNCTION(clearstatcache) efree(BG(CurrentStatFile)); BG(CurrentStatFile) = NULL; } + if (BG(CurrentLStatFile)) { + efree(BG(CurrentLStatFile)); + BG(CurrentLStatFile) = NULL; + } } /* }}} */ #define IS_LINK_OPERATION(__t) ((__t) == FS_TYPE || (__t) == FS_IS_LINK || (__t) == FS_LSTAT) #define IS_EXISTS_CHECK(__t) ((__t) == FS_EXISTS || (__t) == FS_IS_W || (__t) == FS_IS_R || (__t) == FS_IS_X || (__t) == FS_IS_FILE || (__t) == FS_IS_DIR || (__t) == FS_IS_LINK) +#define IS_ABLE_CHECK(__t) ((__t) == FS_IS_R || (__t) == FS_IS_W || (__t) == FS_IS_X) /* {{{ php_stat */ @@ -543,6 +551,7 @@ PHPAPI void php_stat(const char *filename, php_stat_len filename_length, int typ #else struct stat *stat_sb; #endif + php_stream_statbuf ssb; int rmask=S_IROTH, wmask=S_IWOTH, xmask=S_IXOTH; /* access rights defaults to other */ char *stat_sb_names[13]={"dev", "ino", "mode", "nlink", "uid", "gid", "rdev", "size", "atime", "mtime", "ctime", "blksize", "blocks"}; @@ -559,65 +568,25 @@ PHPAPI void php_stat(const char *filename, php_stat_len filename_length, int typ RETURN_FALSE; } - switch (type) { - case FS_IS_W: - RETURN_BOOL (!VCWD_ACCESS(filename, W_OK)); - case FS_IS_R: - RETURN_BOOL (!VCWD_ACCESS(filename, R_OK)); - case FS_IS_X: - RETURN_BOOL (!VCWD_ACCESS(filename, X_OK)); - case FS_EXISTS: - RETURN_BOOL (!VCWD_ACCESS(filename, F_OK)); - } - - stat_sb = &BG(sb); - - if (!BG(CurrentStatFile) || strcmp(filename, BG(CurrentStatFile))) { - if (!BG(CurrentStatFile) || filename_length > BG(CurrentStatLength)) { - if (BG(CurrentStatFile)) { - efree(BG(CurrentStatFile)); - } - BG(CurrentStatLength) = filename_length; - BG(CurrentStatFile) = estrndup(filename, filename_length); - } else { - memcpy(BG(CurrentStatFile), filename, filename_length+1); - } -#if HAVE_SYMLINK - BG(lsb).st_mode = 0; /* mark lstat buf invalid */ -#endif - if (VCWD_STAT(BG(CurrentStatFile), &BG(sb)) == -1) { - if (!IS_LINK_OPERATION(type) && (!IS_EXISTS_CHECK(type) || (errno != ENOENT && errno != ENOTDIR))) { /* fileexists() test must print no error */ - php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Stat failed for %s (errno=%d - %s)", BG(CurrentStatFile), errno, strerror(errno)); - } - efree(BG(CurrentStatFile)); - BG(CurrentStatFile) = NULL; -#if HAVE_SYMLINK - if (!IS_LINK_OPERATION(type)) /* Don't require success for link operation */ -#endif - RETURN_FALSE; - } - } -#if HAVE_SYMLINK - if (IS_LINK_OPERATION(type) && !BG(lsb).st_mode) { - /* do lstat if the buffer is empty */ - if (VCWD_LSTAT(filename, &BG(lsb)) == -1) { - if (!IS_EXISTS_CHECK(type) || (errno != ENOENT && errno != ENOTDIR)) { /* fileexists() test must print no error */ - php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Lstat failed for %s (errno=%d - %s)", BG(CurrentStatFile), errno, strerror(errno)); - } - RETURN_FALSE; + if (php_stream_stat_path_ex((char *)filename, (IS_LINK_OPERATION(type) ? PHP_STREAM_URL_STAT_LINK : 0), &ssb, NULL)) { + /* Error Occured */ + if (!IS_EXISTS_CHECK(type)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "%sstat failed for %s", IS_LINK_OPERATION(type) ? "L" : "", filename); } + RETURN_FALSE; } -#endif + + stat_sb = &ssb.sb; #ifndef NETWARE if (type >= FS_IS_W && type <= FS_IS_X) { - if(BG(sb).st_uid==getuid()) { + if(ssb.sb.st_uid==getuid()) { rmask=S_IRUSR; wmask=S_IWUSR; xmask=S_IXUSR; - } else if(BG(sb).st_gid==getgid()) { + } else if(ssb.sb.st_gid==getgid()) { rmask=S_IRGRP; wmask=S_IWGRP; xmask=S_IXGRP; @@ -630,7 +599,7 @@ PHPAPI void php_stat(const char *filename, php_stat_len filename_length, int typ gids=(gid_t *)safe_emalloc(groups, sizeof(gid_t), 0); n=getgroups(groups, gids); for(i=0;i<n;i++){ - if(BG(sb).st_gid==gids[i]) { + if(ssb.sb.st_gid==gids[i]) { rmask=S_IRGRP; wmask=S_IWGRP; xmask=S_IXGRP; @@ -643,46 +612,61 @@ PHPAPI void php_stat(const char *filename, php_stat_len filename_length, int typ } #endif +#ifndef NETWARE + if (IS_ABLE_CHECK(type) && getuid() == 0) { + /* root has special perms on plain_wrapper + But we don't know about root under Netware */ + php_stream_wrapper *wrapper; + + wrapper = php_stream_locate_url_wrapper(filename, NULL, 0 TSRMLS_CC); + if (wrapper && wrapper->wops && wrapper->wops->label && strcmp(wrapper->wops->label, "plainfile") == 0) { + if (type == FS_IS_X) { + xmask = S_IXROOT; + } else { + RETURN_TRUE; + } + } + } +#endif + switch (type) { case FS_PERMS: - RETURN_LONG((long)BG(sb).st_mode); + RETURN_LONG((long)ssb.sb.st_mode); case FS_INODE: - RETURN_LONG((long)BG(sb).st_ino); + RETURN_LONG((long)ssb.sb.st_ino); case FS_SIZE: #if defined(NETWARE) && defined(NEW_LIBC) RETURN_LONG((long)(stat_sb->st_size)); #else - RETURN_LONG((long)BG(sb).st_size); + RETURN_LONG((long)ssb.sb.st_size); #endif case FS_OWNER: - RETURN_LONG((long)BG(sb).st_uid); + RETURN_LONG((long)ssb.sb.st_uid); case FS_GROUP: - RETURN_LONG((long)BG(sb).st_gid); + RETURN_LONG((long)ssb.sb.st_gid); case FS_ATIME: #if defined(NETWARE) && defined(NEW_LIBC) RETURN_LONG((long)((stat_sb->st_atime).tv_sec)); #else - RETURN_LONG((long)BG(sb).st_atime); + RETURN_LONG((long)ssb.sb.st_atime); #endif case FS_MTIME: #if defined(NETWARE) && defined(NEW_LIBC) RETURN_LONG((long)((stat_sb->st_mtime).tv_sec)); #else - RETURN_LONG((long)BG(sb).st_mtime); + RETURN_LONG((long)ssb.sb.st_mtime); #endif case FS_CTIME: #if defined(NETWARE) && defined(NEW_LIBC) RETURN_LONG((long)((stat_sb->st_ctime).tv_sec)); #else - RETURN_LONG((long)BG(sb).st_ctime); + RETURN_LONG((long)ssb.sb.st_ctime); #endif case FS_TYPE: -#if HAVE_SYMLINK - if (S_ISLNK(BG(lsb).st_mode)) { + if (S_ISLNK(ssb.sb.st_mode)) { RETURN_STRING("link", 1); } -#endif - switch(BG(sb).st_mode&S_IFMT) { + switch(ssb.sb.st_mode & S_IFMT) { case S_IFIFO: RETURN_STRING("fifo", 1); case S_IFCHR: RETURN_STRING("char", 1); case S_IFDIR: RETURN_STRING("dir", 1); @@ -692,45 +676,23 @@ PHPAPI void php_stat(const char *filename, php_stat_len filename_length, int typ case S_IFSOCK: RETURN_STRING("socket", 1); #endif } - php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unknown file type (%d)", BG(sb).st_mode&S_IFMT); + php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unknown file type (%d)", ssb.sb.st_mode&S_IFMT); RETURN_STRING("unknown", 1); case FS_IS_W: -#ifndef NETWARE /* getuid is not available on NetWare */ - if (getuid()==0) { - RETURN_TRUE; /* root */ - } -#endif /* NETWARE */ - RETURN_BOOL((BG(sb).st_mode & wmask) != 0); + RETURN_BOOL((ssb.sb.st_mode & wmask) != 0); case FS_IS_R: -#ifndef NETWARE /* getuid is not available on NetWare */ - if (getuid()==0) { - RETURN_TRUE; /* root */ - } -#endif /* NETWARE */ - RETURN_BOOL((BG(sb).st_mode&rmask)!=0); + RETURN_BOOL((ssb.sb.st_mode&rmask)!=0); case FS_IS_X: -#ifndef NETWARE /* getuid is not available on NetWare */ - if (getuid()==0) { - xmask = S_IXROOT; /* root */ - } -#endif /* NETWARE */ - RETURN_BOOL((BG(sb).st_mode&xmask)!=0 && !S_ISDIR(BG(sb).st_mode)); + RETURN_BOOL((ssb.sb.st_mode&xmask)!=0 && !S_ISDIR(ssb.sb.st_mode)); case FS_IS_FILE: - RETURN_BOOL(S_ISREG(BG(sb).st_mode)); + RETURN_BOOL(S_ISREG(ssb.sb.st_mode)); case FS_IS_DIR: - RETURN_BOOL(S_ISDIR(BG(sb).st_mode)); + RETURN_BOOL(S_ISDIR(ssb.sb.st_mode)); case FS_IS_LINK: -#if HAVE_SYMLINK - RETURN_BOOL(S_ISLNK(BG(lsb).st_mode)); -#else - RETURN_FALSE; -#endif + RETURN_BOOL(S_ISLNK(ssb.sb.st_mode)); case FS_EXISTS: RETURN_TRUE; /* the false case was done earlier */ case FS_LSTAT: -#if HAVE_SYMLINK - stat_sb = &BG(lsb); -#endif /* FALLTHROUGH */ case FS_STAT: array_init(return_value); diff --git a/ext/standard/ftp_fopen_wrapper.c b/ext/standard/ftp_fopen_wrapper.c index 8d20a1a3ae..0405b5b9bc 100644 --- a/ext/standard/ftp_fopen_wrapper.c +++ b/ext/standard/ftp_fopen_wrapper.c @@ -712,7 +712,7 @@ php_stream * php_stream_ftp_opendir(php_stream_wrapper *wrapper, char *path, cha /* {{{ php_stream_ftp_url_stat */ -static int php_stream_ftp_url_stat(php_stream_wrapper *wrapper, char *url, php_stream_statbuf *ssb TSRMLS_DC) +static int php_stream_ftp_url_stat(php_stream_wrapper *wrapper, char *url, int flags, php_stream_statbuf *ssb, php_stream_context *context TSRMLS_DC) { php_stream *stream = NULL; php_url *resource = NULL; @@ -723,7 +723,7 @@ static int php_stream_ftp_url_stat(php_stream_wrapper *wrapper, char *url, php_s if (!ssb) return -1; memset(ssb, 0, sizeof(php_stream_statbuf)); - stream = php_ftp_fopen_connect(wrapper, url, "r", 0, NULL, NULL, NULL, &resource, NULL, NULL TSRMLS_CC); + stream = php_ftp_fopen_connect(wrapper, url, "r", 0, NULL, NULL, context, &resource, NULL, NULL TSRMLS_CC); if (!stream) { goto stat_errexit; } diff --git a/main/php_streams.h b/main/php_streams.h index 6496018931..fac56a06d1 100755 --- a/main/php_streams.h +++ b/main/php_streams.h @@ -139,7 +139,7 @@ typedef struct _php_stream_wrapper_ops { /* stat a wrapped stream */ int (*stream_stat)(php_stream_wrapper *wrapper, php_stream *stream, php_stream_statbuf *ssb TSRMLS_DC); /* stat a URL */ - int (*url_stat)(php_stream_wrapper *wrapper, char *url, php_stream_statbuf *ssb TSRMLS_DC); + int (*url_stat)(php_stream_wrapper *wrapper, char *url, int flags, php_stream_statbuf *ssb, php_stream_context *context TSRMLS_DC); /* open a "directory" stream */ php_stream *(*dir_opener)(php_stream_wrapper *wrapper, char *filename, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC); @@ -301,8 +301,9 @@ PHPAPI int _php_stream_puts(php_stream *stream, char *buf TSRMLS_DC); PHPAPI int _php_stream_stat(php_stream *stream, php_stream_statbuf *ssb TSRMLS_DC); #define php_stream_stat(stream, ssb) _php_stream_stat((stream), (ssb) TSRMLS_CC) -PHPAPI int _php_stream_stat_path(char *path, php_stream_statbuf *ssb TSRMLS_DC); -#define php_stream_stat_path(path, ssb) _php_stream_stat_path((path), (ssb) TSRMLS_CC) +PHPAPI int _php_stream_stat_path(char *path, int flags, php_stream_statbuf *ssb, php_stream_context *context TSRMLS_DC); +#define php_stream_stat_path(path, ssb) _php_stream_stat_path((path), 0, (ssb), NULL TSRMLS_CC) +#define php_stream_stat_path_ex(path, flags, ssb, context) _php_stream_stat_path((path), (flags), (ssb), (context) TSRMLS_CC) PHPAPI php_stream *_php_stream_opendir(char *path, int options, php_stream_context *context STREAMS_DC TSRMLS_DC); #define php_stream_opendir(path, options, context) _php_stream_opendir((path), (options), (context) STREAMS_CC TSRMLS_CC) @@ -316,6 +317,9 @@ PHPAPI int _php_stream_set_option(php_stream *stream, int option, int value, voi #define php_stream_set_chunk_size(stream, size) _php_stream_set_option((stream), PHP_STREAM_OPTION_SET_CHUNK_SIZE, (size), NULL TSRMLS_CC) +/* Flags for url_stat method in wrapper ops */ +#define PHP_STREAM_URL_STAT_LINK 1 + /* change the blocking mode of stream: value == 1 => blocking, value == 0 => non-blocking. */ #define PHP_STREAM_OPTION_BLOCKING 1 diff --git a/main/streams/plain_wrapper.c b/main/streams/plain_wrapper.c index 1f060ec666..b78c2d9651 100644 --- a/main/streams/plain_wrapper.c +++ b/main/streams/plain_wrapper.c @@ -896,9 +896,14 @@ static php_stream *php_plain_files_stream_opener(php_stream_wrapper *wrapper, ch return php_stream_fopen_rel(path, mode, opened_path, options); } -static int php_plain_files_url_stater(php_stream_wrapper *wrapper, char *url, php_stream_statbuf *ssb TSRMLS_DC) +static int php_plain_files_url_stater(php_stream_wrapper *wrapper, char *url, int flags, php_stream_statbuf *ssb, php_stream_context *context TSRMLS_DC) { - return VCWD_STAT(url, &ssb->sb); +#ifdef HAVE_SYMLINK + if (flags & PHP_STREAM_URL_STAT_LINK) { + return VCWD_LSTAT(url, &ssb->sb); + } else +#endif + return VCWD_STAT(url, &ssb->sb); } static int php_plain_files_unlink(php_stream_wrapper *wrapper, char *url, int options, php_stream_context *context TSRMLS_DC) diff --git a/main/streams/streams.c b/main/streams/streams.c index 2089281741..c612e4ca4d 100755 --- a/main/streams/streams.c +++ b/main/streams/streams.c @@ -1458,14 +1458,45 @@ PHPAPI php_stream_wrapper *php_stream_locate_url_wrapper(const char *path, char /* }}} */ /* {{{ _php_stream_stat_path */ -PHPAPI int _php_stream_stat_path(char *path, php_stream_statbuf *ssb TSRMLS_DC) +PHPAPI int _php_stream_stat_path(char *path, int flags, php_stream_statbuf *ssb, php_stream_context *context TSRMLS_DC) { php_stream_wrapper *wrapper = NULL; char *path_to_open = path; + int ret; + + /* Try to hit the cache first */ + if (flags & PHP_STREAM_URL_STAT_LINK) { + if (BG(CurrentLStatFile) && strcmp(path, BG(CurrentLStatFile)) == 0) { + memcpy(ssb, &BG(lssb), sizeof(php_stream_statbuf)); + return 0; + } + } else { + if (BG(CurrentStatFile) && strcmp(path, BG(CurrentStatFile)) == 0) { + memcpy(ssb, &BG(ssb), sizeof(php_stream_statbuf)); + return 0; + } + } wrapper = php_stream_locate_url_wrapper(path, &path_to_open, ENFORCE_SAFE_MODE TSRMLS_CC); if (wrapper && wrapper->wops->url_stat) { - return wrapper->wops->url_stat(wrapper, path_to_open, ssb TSRMLS_CC); + ret = wrapper->wops->url_stat(wrapper, path_to_open, flags, ssb, context TSRMLS_CC); + if (ret == 0) { + /* Drop into cache */ + if (flags & PHP_STREAM_URL_STAT_LINK) { + if (BG(CurrentLStatFile)) { + efree(BG(CurrentLStatFile)); + } + BG(CurrentLStatFile) = estrdup(path); + memcpy(&BG(lssb), ssb, sizeof(php_stream_statbuf)); + } else { + if (BG(CurrentStatFile)) { + efree(BG(CurrentStatFile)); + } + BG(CurrentStatFile) = estrdup(path); + memcpy(&BG(ssb), ssb, sizeof(php_stream_statbuf)); + } + } + return ret; } return -1; } |