summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPierre Joye <pajoye@php.net>2009-06-16 00:07:05 +0000
committerPierre Joye <pajoye@php.net>2009-06-16 00:07:05 +0000
commit18d5751a9e8da170ca02ddbe06120c3993c9bf1e (patch)
tree43d5341a69919e3cd6141b406e708846cb3354f4
parentda9b80e30948d31d42de2c2cdf93398691f0c27c (diff)
downloadphp-git-18d5751a9e8da170ca02ddbe06120c3993c9bf1e.tar.gz
- Windows ACL cache support, update existing tests and add a new one
-rw-r--r--TSRM/tsrm_virtual_cwd.c12
-rw-r--r--TSRM/tsrm_virtual_cwd.h7
-rw-r--r--TSRM/tsrm_win32.c85
-rw-r--r--ext/standard/tests/file/windows_acls/bug44859.phpt2
-rw-r--r--ext/standard/tests/file/windows_acls/bug44859_2.phpt6
-rw-r--r--ext/standard/tests/file/windows_acls/bug44859_4.phpt64
-rw-r--r--ext/standard/tests/file/windows_acls/common.inc1
7 files changed, 162 insertions, 15 deletions
diff --git a/TSRM/tsrm_virtual_cwd.c b/TSRM/tsrm_virtual_cwd.c
index 206e31955d..41cd1ff754 100644
--- a/TSRM/tsrm_virtual_cwd.c
+++ b/TSRM/tsrm_virtual_cwd.c
@@ -471,6 +471,12 @@ static inline void realpath_cache_add(const char *path, int path_len, const char
}
bucket->realpath_len = realpath_len;
bucket->is_dir = is_dir;
+#ifdef PHP_WIN32
+ bucket->is_rvalid = 0;
+ bucket->is_readable = 0;
+ bucket->is_wvalid = 0;
+ bucket->is_writable = 0;
+#endif
bucket->expires = t + CWDG(realpath_cache_ttl);
n = bucket->key % (sizeof(CWDG(realpath_cache)) / sizeof(CWDG(realpath_cache)[0]));
bucket->next = CWDG(realpath_cache)[n];
@@ -503,6 +509,12 @@ static inline realpath_cache_bucket* realpath_cache_find(const char *path, int p
}
/* }}} */
+CWD_API realpath_cache_bucket* realpath_cache_lookup(const char *path, int path_len, time_t t TSRMLS_DC) /* {{{ */
+{
+ return realpath_cache_find(path, path_len, t TSRMLS_CC);
+}
+/* }}} */
+
#undef LINK_MAX
#define LINK_MAX 32
diff --git a/TSRM/tsrm_virtual_cwd.h b/TSRM/tsrm_virtual_cwd.h
index 28e93fc7cc..8ddbee6f0f 100644
--- a/TSRM/tsrm_virtual_cwd.h
+++ b/TSRM/tsrm_virtual_cwd.h
@@ -210,6 +210,12 @@ typedef struct _realpath_cache_bucket {
int realpath_len;
int is_dir;
time_t expires;
+#ifdef PHP_WIN32
+ unsigned char is_rvalid;
+ unsigned char is_readable;
+ unsigned char is_wvalid;
+ unsigned char is_writable;
+#endif
struct _realpath_cache_bucket *next;
} realpath_cache_bucket;
@@ -231,6 +237,7 @@ extern virtual_cwd_globals cwd_globals;
CWD_API void realpath_cache_clean(TSRMLS_D);
CWD_API void realpath_cache_del(const char *path, int path_len TSRMLS_DC);
+CWD_API realpath_cache_bucket* realpath_cache_lookup(const char *path, int path_len, time_t t TSRMLS_DC);
/* The actual macros to be used in programs using TSRM
* If the program defines VIRTUAL_DIR it will use the
diff --git a/TSRM/tsrm_win32.c b/TSRM/tsrm_win32.c
index 69214d00d4..187f5e652e 100644
--- a/TSRM/tsrm_win32.c
+++ b/TSRM/tsrm_win32.c
@@ -32,6 +32,7 @@
#ifdef TSRM_WIN32
#include "tsrm_win32.h"
+#include "tsrm_virtual_cwd.h"
#ifdef ZTS
static ts_rsrc_id win32_globals_id;
@@ -114,6 +115,11 @@ TSRM_API int tsrm_win32_access(const char *pathname, int mode)
BYTE * psec_desc = NULL;
BOOL fAccess = FALSE;
HANDLE process_token = NULL;
+
+ realpath_cache_bucket * bucket = NULL;
+ char * real_path = NULL;
+ time_t t;
+
TSRMLS_FETCH();
if (mode == 1 /*X_OK*/) {
@@ -121,24 +127,62 @@ TSRM_API int tsrm_win32_access(const char *pathname, int mode)
return GetBinaryType(pathname, &type) ? 0 : -1;
} else {
if(access(pathname, mode)) {
- return errno;
+ return errno;
}
+ if(!IS_ABSOLUTE_PATH(pathname, strlen(pathname)+1)) {
+ real_path = (char *)malloc(MAX_PATH);
+ if(tsrm_realpath(pathname, real_path TSRMLS_CC) == NULL) {
+ goto Finished;
+ }
+ pathname = real_path;
+ }
+
+ if (CWDG(realpath_cache_size_limit)) {
+ t = time(0);
+ bucket = realpath_cache_lookup(pathname, strlen(pathname), t TSRMLS_CC);
+ if(bucket == NULL && real_path == NULL) {
+ /* We used the pathname directly. Call tsrm_realpath */
+ /* so that entry is created in realpath cache */
+ real_path = (char *)malloc(MAX_PATH);
+ if(tsrm_realpath(pathname, real_path TSRMLS_CC) != NULL) {
+ pathname = real_path;
+ bucket = realpath_cache_lookup(pathname, strlen(pathname), t TSRMLS_CC);
+ }
+ }
+ }
+
+ /* Do a full access check because access() will only check read-only attribute */
+ if(mode == 0 || mode > 6) {
+ if(bucket != NULL && bucket->is_rvalid) {
+ fAccess = bucket->is_readable;
+ goto Finished;
+ }
+ desired_access = FILE_GENERIC_READ;
+ } else if(mode <= 2) {
+ if(bucket != NULL && bucket->is_wvalid) {
+ fAccess = bucket->is_writable;
+ goto Finished;
+ }
+ desired_access = FILE_GENERIC_WRITE;
+ } else if(mode <= 4) {
+ if(bucket != NULL && bucket->is_rvalid) {
+ fAccess = bucket->is_readable;
+ goto Finished;
+ }
+ desired_access = FILE_GENERIC_READ;
+ } else { // if(mode <= 6)
+ if(bucket != NULL && bucket->is_rvalid && bucket->is_wvalid) {
+ fAccess = bucket->is_readable & bucket->is_writable;
+ goto Finished;
+ }
+ desired_access = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
+ }
+
if(TWG(impersonation_token) == NULL) {
goto Finished;
}
- /* Do a full access check because access() will only check read-only attribute */
- if(mode == 0 || mode > 6) {
- desired_access = FILE_GENERIC_READ;
- } else if(mode <= 2) {
- desired_access = FILE_GENERIC_WRITE;
- } else if(mode <= 4) {
- desired_access = FILE_GENERIC_READ;
- } else { // if(mode <= 6)
- desired_access = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
- }
-
/* Get size of security buffer. Call is expected to fail */
if(GetFileSecurity(pathname, sec_info, NULL, 0, &sec_desc_length)) {
goto Finished;
@@ -154,12 +198,29 @@ TSRM_API int tsrm_win32_access(const char *pathname, int mode)
goto Finished;
}
+ /* Keep the result in realpath_cache */
+ if(bucket != NULL) {
+ if(desired_access == FILE_GENERIC_READ) {
+ bucket->is_rvalid = 1;
+ bucket->is_readable = fAccess;
+ }
+ else if(desired_access == FILE_GENERIC_WRITE) {
+ bucket->is_wvalid = 1;
+ bucket->is_writable = fAccess;
+ }
+ }
+
Finished:
if(psec_desc != NULL) {
free(psec_desc);
psec_desc = NULL;
}
+ if(real_path != NULL) {
+ free(real_path);
+ real_path = NULL;
+ }
+
if(fAccess == FALSE) {
errno = EACCES;
return errno;
diff --git a/ext/standard/tests/file/windows_acls/bug44859.phpt b/ext/standard/tests/file/windows_acls/bug44859.phpt
index 0716ee5ac4..bb22a5cd8e 100644
--- a/ext/standard/tests/file/windows_acls/bug44859.phpt
+++ b/ext/standard/tests/file/windows_acls/bug44859.phpt
@@ -21,6 +21,7 @@ $i = 1;
$path = __DIR__ . '/a.txt';
foreach ($iteration as $perms => $exp) {
create_file($path, $perms);
+ clearstatcache(true, $path);
echo 'Iteration #' . $i++ . ': ';
if (is_writable($path) == $exp) {
echo "passed.\n";
@@ -36,6 +37,7 @@ $path = __DIR__ . '/adir';
$i = 1;
foreach ($iteration as $perms => $exp) {
create_file($path, $perms);
+ clearstatcache(true, $path);
echo 'Iteration #' . $i++ . ': ';
if (is_writable($path) == $exp) {
echo "passed.\n";
diff --git a/ext/standard/tests/file/windows_acls/bug44859_2.phpt b/ext/standard/tests/file/windows_acls/bug44859_2.phpt
index 8326eb473e..3cc4ed1ba1 100644
--- a/ext/standard/tests/file/windows_acls/bug44859_2.phpt
+++ b/ext/standard/tests/file/windows_acls/bug44859_2.phpt
@@ -21,11 +21,12 @@ $i = 1;
$path = __DIR__ . '/a.txt';
foreach ($iteration as $perms => $exp) {
create_file($path, $perms);
+ clearstatcache(true, $path);
echo 'Iteration #' . $i++ . ': ';
if (is_readable($path) == $exp) {
echo "passed.\n";
} else {
- var_dump(is_writable($path), $exp);
+ var_dump(is_readable($path), $exp);
echo "failed.\n";
}
delete_file($path);
@@ -36,11 +37,12 @@ $path = __DIR__ . '/adir';
$i = 1;
foreach ($iteration as $perms => $exp) {
create_file($path, $perms);
+ clearstatcache(true, $path);
echo 'Iteration #' . $i++ . ': ';
if (is_readable($path) == $exp) {
echo "passed.\n";
} else {
- var_dump(is_writable($path), $exp);
+ var_dump(is_readable($path), $exp);
echo "failed.\n";
}
delete_file($path);
diff --git a/ext/standard/tests/file/windows_acls/bug44859_4.phpt b/ext/standard/tests/file/windows_acls/bug44859_4.phpt
new file mode 100644
index 0000000000..fff90662e8
--- /dev/null
+++ b/ext/standard/tests/file/windows_acls/bug44859_4.phpt
@@ -0,0 +1,64 @@
+--TEST--
+bug #44859 (incorrect result with NTFS ACL permissions, is_readable)
+--CREDIT--
+Venkat Raman Don
+--SKIPIF--
+<?php
+include_once __DIR__ . '/common.inc';
+skipif();
+?>
+--FILE--
+<?php
+include_once __DIR__ . '/common.inc';
+
+$iteration = array(
+ PHPT_ACL_READ => true,
+ PHPT_ACL_NONE => false,
+ PHPT_ACL_WRITE => false,
+ PHPT_ACL_WRITE|PHPT_ACL_READ => true,
+);
+
+echo "Testing file with relative path:\n";
+$i = 1;
+$path = './a.txt';
+foreach ($iteration as $perms => $exp) {
+ create_file($path, $perms);
+ clearstatcache(true, $path);
+ echo 'Iteration #' . $i++ . ': ';
+ if (is_readable($path) == $exp) {
+ echo "passed.\n";
+ } else {
+ var_dump(is_readable($path), $exp);
+ echo "failed.\n";
+ }
+ delete_file($path);
+}
+
+echo "Testing directory with relative path:\n";
+$path = 'adir';
+$i = 1;
+foreach ($iteration as $perms => $exp) {
+ create_file($path, $perms);
+ clearstatcache(true, $path);
+ echo 'Iteration #' . $i++ . ': ';
+ if (is_readable($path) == $exp) {
+ echo "passed.\n";
+ } else {
+ var_dump(is_readable($path), $exp);
+ echo "failed.\n";
+ }
+ delete_file($path);
+}
+
+?>
+--EXPECT--
+Testing file with relative path:
+Iteration #1: passed.
+Iteration #2: passed.
+Iteration #3: passed.
+Iteration #4: passed.
+Testing directory with relative path:
+Iteration #1: passed.
+Iteration #2: passed.
+Iteration #3: passed.
+Iteration #4: passed.
diff --git a/ext/standard/tests/file/windows_acls/common.inc b/ext/standard/tests/file/windows_acls/common.inc
index 6bcaf2b327..2a1adeb0a4 100644
--- a/ext/standard/tests/file/windows_acls/common.inc
+++ b/ext/standard/tests/file/windows_acls/common.inc
@@ -123,7 +123,6 @@ function create_file($name, $perms) {
}
touch($name);
- $dst = realpath($name);
icacls_set($name, PHPT_ACL_GRANT, $perms);
}