summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSara Golemon <pollita@php.net>2003-11-28 23:25:28 +0000
committerSara Golemon <pollita@php.net>2003-11-28 23:25:28 +0000
commit026d4c9e4cec8cb3f03c311b90f05241f2d70455 (patch)
treee563b6f3699eb94168362c8f00fb1c4d80506e7a
parent6d86bb9e40386e4127af4f55b8e8e79864255ca1 (diff)
downloadphp-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--NEWS1
-rw-r--r--ext/libxml/libxml.c2
-rw-r--r--ext/standard/basic_functions.h8
-rw-r--r--ext/standard/filestat.c146
-rw-r--r--ext/standard/ftp_fopen_wrapper.c4
-rwxr-xr-xmain/php_streams.h10
-rw-r--r--main/streams/plain_wrapper.c9
-rwxr-xr-xmain/streams/streams.c35
8 files changed, 108 insertions, 107 deletions
diff --git a/NEWS b/NEWS
index 6d58f5ffb4..00f03e0678 100644
--- a/NEWS
+++ b/NEWS
@@ -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;
}