Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions Zend/zend_virtual_cwd.c
Original file line number Diff line number Diff line change
Expand Up @@ -1301,6 +1301,27 @@ CWD_API int virtual_filepath(const char *path, char **filepath) /* {{{ */
}
/* }}} */

#ifndef ZEND_WIN32
/* An absolute path without dot segments doesn't need a per-thread CWD emulation */
static zend_always_inline bool virtual_path_is_direct(const char *path)
{
const char *s = path;

if (*s != '/') {
return false;
}
do {
if (s[1] == '.'
&& (s[2] == '\0' || s[2] == '/'
|| (s[2] == '.' && (s[3] == '\0' || s[3] == '/')))) {
return false;
}
s = strchr(s + 1, '/');
} while (s != NULL);
return true;
}
#endif

CWD_API FILE *virtual_fopen(const char *path, const char *mode) /* {{{ */
{
cwd_state new_state;
Expand All @@ -1310,6 +1331,12 @@ CWD_API FILE *virtual_fopen(const char *path, const char *mode) /* {{{ */
return NULL;
}

#ifndef ZEND_WIN32
if (virtual_path_is_direct(path)) {
return fopen(path, mode);
Comment thread
henderkes marked this conversation as resolved.
}
#endif

CWD_STATE_COPY(&new_state, &CWDG(cwd));
if (virtual_file_ex(&new_state, path, NULL, CWD_EXPAND)) {
CWD_STATE_FREE_ERR(&new_state);
Expand All @@ -1333,6 +1360,12 @@ CWD_API int virtual_access(const char *pathname, int mode) /* {{{ */
cwd_state new_state;
int ret;

#ifndef ZEND_WIN32
if (pathname[0] == '/') {
return access(pathname, mode);
}
#endif

CWD_STATE_COPY(&new_state, &CWDG(cwd));
if (virtual_file_ex(&new_state, pathname, NULL, CWD_REALPATH)) {
CWD_STATE_FREE_ERR(&new_state);
Expand Down Expand Up @@ -1442,6 +1475,21 @@ CWD_API int virtual_open(const char *path, int flags, ...) /* {{{ */
cwd_state new_state;
int f;

#ifndef ZEND_WIN32
if (virtual_path_is_direct(path)) {
if (flags & O_CREAT) {
mode_t mode;
va_list arg;

va_start(arg, flags);
mode = (mode_t) va_arg(arg, int);
va_end(arg);
return open(path, flags, mode);
}
return open(path, flags);
}
#endif

CWD_STATE_COPY(&new_state, &CWDG(cwd));
if (virtual_file_ex(&new_state, path, NULL, CWD_FILEPATH)) {
CWD_STATE_FREE_ERR(&new_state);
Expand Down Expand Up @@ -1533,6 +1581,12 @@ CWD_API int virtual_stat(const char *path, zend_stat_t *buf) /* {{{ */
cwd_state new_state;
int retval;

#ifndef ZEND_WIN32
if (path[0] == '/') {
return php_sys_stat(path, buf);
}
#endif

CWD_STATE_COPY(&new_state, &CWDG(cwd));
if (virtual_file_ex(&new_state, path, NULL, CWD_REALPATH)) {
CWD_STATE_FREE_ERR(&new_state);
Expand All @@ -1551,6 +1605,15 @@ CWD_API int virtual_lstat(const char *path, zend_stat_t *buf) /* {{{ */
cwd_state new_state;
int retval;

#ifndef ZEND_WIN32
/* CWD_EXPAND strips '..' textually (save=0 -> no symlink lookups),
* but the kernel resolves it physically. Different file
* when a parent component is a symlink. */
if (virtual_path_is_direct(path)) {
return php_sys_lstat(path, buf);
}
#endif

CWD_STATE_COPY(&new_state, &CWDG(cwd));
if (virtual_file_ex(&new_state, path, NULL, CWD_EXPAND)) {
CWD_STATE_FREE_ERR(&new_state);
Expand Down Expand Up @@ -1637,6 +1700,12 @@ CWD_API DIR *virtual_opendir(const char *pathname) /* {{{ */
cwd_state new_state;
DIR *retval;

#ifndef ZEND_WIN32
if (virtual_path_is_direct(pathname)) {
return opendir(pathname);
}
#endif

CWD_STATE_COPY(&new_state, &CWDG(cwd));
if (virtual_file_ex(&new_state, pathname, NULL, CWD_REALPATH)) {
CWD_STATE_FREE_ERR(&new_state);
Expand Down
Loading