Skip to content

Virtual cwd refactoring #15524

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 12 commits into
base: master
Choose a base branch
from
140 changes: 76 additions & 64 deletions Zend/zend_virtual_cwd.c
Original file line number Diff line number Diff line change
Expand Up @@ -1004,9 +1004,8 @@ static size_t tsrm_realpath_r(char *path, size_t start, size_t len, int *ll, tim

/* Resolve path relatively to state and put the real path into state */
/* returns 0 for ok, 1 for error, -1 if (path_length >= MAXPATHLEN-1) */
CWD_API int virtual_file_ex(cwd_state *state, const char *path, verify_path_func verify_path, int use_realpath) /* {{{ */
CWD_API int virtual_file_ex(cwd_state *state, const char *path, size_t path_length, verify_path_func verify_path, int use_realpath) /* {{{ */
{
size_t path_length = strlen(path);
char resolved_path[MAXPATHLEN];
size_t start = 1;
int ll = 0;
Expand Down Expand Up @@ -1202,43 +1201,43 @@ CWD_API int virtual_file_ex(cwd_state *state, const char *path, verify_path_func

CWD_API zend_result virtual_chdir(const char *path) /* {{{ */
{
return virtual_file_ex(&CWDG(cwd), path, php_is_dir_ok, CWD_REALPATH) ? FAILURE : SUCCESS;
size_t path_length = strlen(path);
return virtual_file_ex(&CWDG(cwd), path, path_length, php_is_dir_ok, CWD_REALPATH) ? FAILURE : SUCCESS;
}
/* }}} */


/* returns 0 for ok, 1 for empty string, -1 on error */
CWD_API int virtual_chdir_file(const char *path, int (*p_chdir)(const char *path)) /* {{{ */
CWD_API zend_result virtual_chdir_file(const char *path, size_t path_len, int (*p_chdir)(const char *path)) /* {{{ */
{
size_t length = strlen(path);
char *temp;
int retval;
ALLOCA_FLAG(use_heap)

if (length == 0) {
return 1; /* Can't cd to empty string */
}
while(--length < SIZE_MAX && !IS_SLASH(path[length])) {
ZEND_ASSERT(path_len != 0 && "path must not be empty");
while(--path_len < SIZE_MAX && !IS_SLASH(path[path_len])) {
}

if (length == SIZE_MAX) {
if (path_len == SIZE_MAX) {
/* No directory only file name */
errno = ENOENT;
return -1;
return FAILURE;
}

if (length == COPY_WHEN_ABSOLUTE(path) && IS_ABSOLUTE_PATH(path, length+1)) { /* Also use trailing slash if this is absolute */
length++;
if (path_len == COPY_WHEN_ABSOLUTE(path) && IS_ABSOLUTE_PATH(path, path_len+1)) { /* Also use trailing slash if this is absolute */
path_len++;
}
temp = (char *) do_alloca(length+1, use_heap);
memcpy(temp, path, length);
temp[length] = 0;
temp = (char *) do_alloca(path_len+1, use_heap);
memcpy(temp, path, path_len);
temp[path_len] = 0;
#if VIRTUAL_CWD_DEBUG
fprintf (stderr, "Changing directory to %s\n", temp);
#endif
retval = p_chdir(temp);
int retval = p_chdir(temp);
free_alloca(temp, use_heap);
return retval;

if (retval == 0) {
return SUCCESS;
} else {
return FAILURE;
}
}
/* }}} */

Expand All @@ -1247,24 +1246,26 @@ CWD_API char *virtual_realpath(const char *path, char *real_path) /* {{{ */
cwd_state new_state;
char *retval;
char cwd[MAXPATHLEN];
size_t path_length = strlen(path);

/* realpath("") returns CWD */
if (!*path) {
if (path_length == 0) {
new_state.cwd = (char*)emalloc(1);
new_state.cwd[0] = '\0';
new_state.cwd_length = 0;
if (VCWD_GETCWD(cwd, MAXPATHLEN)) {
path = cwd;
path_length = strlen(cwd);
}
} else if (!IS_ABSOLUTE_PATH(path, strlen(path))) {
} else if (!IS_ABSOLUTE_PATH(path, path_length)) {
CWD_STATE_COPY(&new_state, &CWDG(cwd));
} else {
new_state.cwd = (char*)emalloc(1);
new_state.cwd[0] = '\0';
new_state.cwd_length = 0;
}

if (virtual_file_ex(&new_state, path, NULL, CWD_REALPATH)==0) {
if (virtual_file_ex(&new_state, path, path_length, NULL, CWD_REALPATH)==0) {
size_t len = new_state.cwd_length>MAXPATHLEN-1?MAXPATHLEN-1:new_state.cwd_length;

memcpy(real_path, new_state.cwd, len);
Expand All @@ -1283,10 +1284,11 @@ CWD_API char *virtual_realpath(const char *path, char *real_path) /* {{{ */
CWD_API int virtual_filepath_ex(const char *path, char **filepath, verify_path_func verify_path) /* {{{ */
{
cwd_state new_state;
size_t path_length = strlen(path);
int retval;

CWD_STATE_COPY(&new_state, &CWDG(cwd));
retval = virtual_file_ex(&new_state, path, verify_path, CWD_FILEPATH);
retval = virtual_file_ex(&new_state, path, path_length, verify_path, CWD_FILEPATH);

*filepath = new_state.cwd;

Expand All @@ -1305,14 +1307,15 @@ CWD_API int virtual_filepath(const char *path, char **filepath) /* {{{ */
CWD_API FILE *virtual_fopen(const char *path, const char *mode) /* {{{ */
{
cwd_state new_state;
size_t path_length = strlen(path);
FILE *f;

if (path[0] == '\0') { /* Fail to open empty path */
return NULL;
}

CWD_STATE_COPY(&new_state, &CWDG(cwd));
if (virtual_file_ex(&new_state, path, NULL, CWD_EXPAND)) {
if (virtual_file_ex(&new_state, path, path_length, NULL, CWD_EXPAND)) {
CWD_STATE_FREE_ERR(&new_state);
return NULL;
}
Expand All @@ -1332,10 +1335,11 @@ CWD_API FILE *virtual_fopen(const char *path, const char *mode) /* {{{ */
CWD_API int virtual_access(const char *pathname, int mode) /* {{{ */
{
cwd_state new_state;
size_t path_length = strlen(pathname);
int ret;

CWD_STATE_COPY(&new_state, &CWDG(cwd));
if (virtual_file_ex(&new_state, pathname, NULL, CWD_REALPATH)) {
if (virtual_file_ex(&new_state, pathname, path_length, NULL, CWD_REALPATH)) {
CWD_STATE_FREE_ERR(&new_state);
return -1;
}
Expand All @@ -1356,10 +1360,11 @@ CWD_API int virtual_access(const char *pathname, int mode) /* {{{ */
CWD_API int virtual_utime(const char *filename, struct utimbuf *buf) /* {{{ */
{
cwd_state new_state;
size_t filename_length = strlen(filename);
int ret;

CWD_STATE_COPY(&new_state, &CWDG(cwd));
if (virtual_file_ex(&new_state, filename, NULL, CWD_REALPATH)) {
if (virtual_file_ex(&new_state, filename, filename_length, NULL, CWD_REALPATH)) {
CWD_STATE_FREE_ERR(&new_state);
return -1;
}
Expand All @@ -1379,10 +1384,11 @@ CWD_API int virtual_utime(const char *filename, struct utimbuf *buf) /* {{{ */
CWD_API int virtual_chmod(const char *filename, mode_t mode) /* {{{ */
{
cwd_state new_state;
size_t filename_length = strlen(filename);
int ret;

CWD_STATE_COPY(&new_state, &CWDG(cwd));
if (virtual_file_ex(&new_state, filename, NULL, CWD_REALPATH)) {
if (virtual_file_ex(&new_state, filename, filename_length, NULL, CWD_REALPATH)) {
CWD_STATE_FREE_ERR(&new_state);
return -1;
}
Expand Down Expand Up @@ -1414,10 +1420,11 @@ CWD_API int virtual_chmod(const char *filename, mode_t mode) /* {{{ */
CWD_API int virtual_chown(const char *filename, uid_t owner, gid_t group, int link) /* {{{ */
{
cwd_state new_state;
size_t filename_length = strlen(filename);
int ret;

CWD_STATE_COPY(&new_state, &CWDG(cwd));
if (virtual_file_ex(&new_state, filename, NULL, CWD_REALPATH)) {
if (virtual_file_ex(&new_state, filename, filename_length, NULL, CWD_REALPATH)) {
CWD_STATE_FREE_ERR(&new_state);
return -1;
}
Expand All @@ -1441,10 +1448,11 @@ CWD_API int virtual_chown(const char *filename, uid_t owner, gid_t group, int li
CWD_API int virtual_open(const char *path, int flags, ...) /* {{{ */
{
cwd_state new_state;
size_t path_length = strlen(path);
int f;

CWD_STATE_COPY(&new_state, &CWDG(cwd));
if (virtual_file_ex(&new_state, path, NULL, CWD_FILEPATH)) {
if (virtual_file_ex(&new_state, path, path_length, NULL, CWD_FILEPATH)) {
CWD_STATE_FREE_ERR(&new_state);
return -1;
}
Expand Down Expand Up @@ -1477,10 +1485,11 @@ CWD_API int virtual_open(const char *path, int flags, ...) /* {{{ */
CWD_API int virtual_creat(const char *path, mode_t mode) /* {{{ */
{
cwd_state new_state;
size_t path_length = strlen(path);
int f;

CWD_STATE_COPY(&new_state, &CWDG(cwd));
if (virtual_file_ex(&new_state, path, NULL, CWD_FILEPATH)) {
if (virtual_file_ex(&new_state, path, path_length, NULL, CWD_FILEPATH)) {
CWD_STATE_FREE_ERR(&new_state);
return -1;
}
Expand All @@ -1492,34 +1501,31 @@ CWD_API int virtual_creat(const char *path, mode_t mode) /* {{{ */
}
/* }}} */

CWD_API int virtual_rename(const char *oldname, const char *newname) /* {{{ */
CWD_API zend_result virtual_rename(const char *old_name, size_t old_name_len, const char *new_name, size_t new_name_len) /* {{{ */
{
cwd_state old_state;
cwd_state new_state;
int retval;

CWD_STATE_COPY(&old_state, &CWDG(cwd));
if (virtual_file_ex(&old_state, oldname, NULL, CWD_EXPAND)) {
if (virtual_file_ex(&old_state, old_name, old_name_len, NULL, CWD_EXPAND)) {
CWD_STATE_FREE_ERR(&old_state);
return -1;
return FAILURE;
}
oldname = old_state.cwd;

CWD_STATE_COPY(&new_state, &CWDG(cwd));
if (virtual_file_ex(&new_state, newname, NULL, CWD_EXPAND)) {
if (virtual_file_ex(&new_state, new_name, new_name_len, NULL, CWD_EXPAND)) {
CWD_STATE_FREE_ERR(&old_state);
CWD_STATE_FREE_ERR(&new_state);
return -1;
return FAILURE;
}
newname = new_state.cwd;

/* rename on windows will fail if newname already exists.
MoveFileEx has to be used */
zend_result retval;
#ifdef ZEND_WIN32
/* MoveFileEx returns 0 on failure, other way 'round for this function */
retval = php_win32_ioutil_rename(oldname, newname);
/* rename on windows will fail if new_name already exists. MoveFileEx has to be used */
/* MoveFileEx returns 0 on failure, other way round for this function */
retval = php_win32_ioutil_rename(old_state.cwd, old_state.cwd_length, new_name, new_name_len);
#else
retval = rename(oldname, newname);
retval = virtual_rename_native(old_state.cwd, old_state.cwd_length, new_state.cwd, new_state.cwd_length);
#endif

CWD_STATE_FREE_ERR(&old_state);
Expand All @@ -1533,9 +1539,10 @@ CWD_API int virtual_stat(const char *path, zend_stat_t *buf) /* {{{ */
{
cwd_state new_state;
int retval;
size_t path_length = strlen(path);

CWD_STATE_COPY(&new_state, &CWDG(cwd));
if (virtual_file_ex(&new_state, path, NULL, CWD_REALPATH)) {
if (virtual_file_ex(&new_state, path, path_length, NULL, CWD_REALPATH)) {
CWD_STATE_FREE_ERR(&new_state);
return -1;
}
Expand All @@ -1551,9 +1558,10 @@ CWD_API int virtual_lstat(const char *path, zend_stat_t *buf) /* {{{ */
{
cwd_state new_state;
int retval;
size_t path_length = strlen(path);

CWD_STATE_COPY(&new_state, &CWDG(cwd));
if (virtual_file_ex(&new_state, path, NULL, CWD_EXPAND)) {
if (virtual_file_ex(&new_state, path, path_length, NULL, CWD_EXPAND)) {
CWD_STATE_FREE_ERR(&new_state);
return -1;
}
Expand All @@ -1565,21 +1573,21 @@ CWD_API int virtual_lstat(const char *path, zend_stat_t *buf) /* {{{ */
}
/* }}} */

CWD_API int virtual_unlink(const char *path) /* {{{ */
CWD_API zend_result virtual_unlink(const char *path, size_t path_length) /* {{{ */
{
cwd_state new_state;
int retval;
zend_result retval;

CWD_STATE_COPY(&new_state, &CWDG(cwd));
if (virtual_file_ex(&new_state, path, NULL, CWD_EXPAND)) {
if (virtual_file_ex(&new_state, path, path_length, NULL, CWD_EXPAND)) {
CWD_STATE_FREE_ERR(&new_state);
return -1;
return FAILURE;
}

#ifdef ZEND_WIN32
retval = php_win32_ioutil_unlink(new_state.cwd);
retval = php_win32_ioutil_unlink(new_state.cwd, new_state.cwd_length);
#else
retval = unlink(new_state.cwd);
retval = virtual_unlink_native(new_state.cwd, new_state.cwd_length);
#endif

CWD_STATE_FREE_ERR(&new_state);
Expand All @@ -1591,9 +1599,10 @@ CWD_API int virtual_mkdir(const char *pathname, mode_t mode) /* {{{ */
{
cwd_state new_state;
int retval;
size_t path_length = strlen(pathname);

CWD_STATE_COPY(&new_state, &CWDG(cwd));
if (virtual_file_ex(&new_state, pathname, NULL, CWD_FILEPATH)) {
if (virtual_file_ex(&new_state, pathname, path_length, NULL, CWD_FILEPATH)) {
CWD_STATE_FREE_ERR(&new_state);
return -1;
}
Expand All @@ -1608,21 +1617,21 @@ CWD_API int virtual_mkdir(const char *pathname, mode_t mode) /* {{{ */
}
/* }}} */

CWD_API int virtual_rmdir(const char *pathname) /* {{{ */
CWD_API zend_result virtual_rmdir(const char *path, size_t path_length) /* {{{ */
{
cwd_state new_state;
int retval;

CWD_STATE_COPY(&new_state, &CWDG(cwd));
if (virtual_file_ex(&new_state, pathname, NULL, CWD_EXPAND)) {
if (virtual_file_ex(&new_state, path, path_length, NULL, CWD_EXPAND)) {
CWD_STATE_FREE_ERR(&new_state);
return -1;
return FAILURE;
}

zend_result retval;
#ifdef ZEND_WIN32
retval = php_win32_ioutil_rmdir(new_state.cwd);
retval = php_win32_ioutil_rmdir(new_state.cwd, new_state.cwd_length);
#else
retval = rmdir(new_state.cwd);
retval = virtual_rmdir_native(new_state.cwd, new_state.cwd_length);
#endif
CWD_STATE_FREE_ERR(&new_state);
return retval;
Expand All @@ -1637,9 +1646,10 @@ CWD_API DIR *virtual_opendir(const char *pathname) /* {{{ */
{
cwd_state new_state;
DIR *retval;
size_t path_length = strlen(pathname);

CWD_STATE_COPY(&new_state, &CWDG(cwd));
if (virtual_file_ex(&new_state, pathname, NULL, CWD_REALPATH)) {
if (virtual_file_ex(&new_state, pathname, path_length, NULL, CWD_REALPATH)) {
CWD_STATE_FREE_ERR(&new_state);
return NULL;
}
Expand Down Expand Up @@ -1718,16 +1728,18 @@ CWD_API char *tsrm_realpath(const char *path, char *real_path) /* {{{ */
{
cwd_state new_state;
char cwd[MAXPATHLEN];
size_t path_length = strlen(path);

/* realpath("") returns CWD */
if (!*path) {
if (path_length == 0) {
new_state.cwd = (char*)emalloc(1);
new_state.cwd[0] = '\0';
new_state.cwd_length = 0;
if (VCWD_GETCWD(cwd, MAXPATHLEN)) {
path = cwd;
path_length = strlen(cwd);
}
} else if (!IS_ABSOLUTE_PATH(path, strlen(path)) &&
} else if (!IS_ABSOLUTE_PATH(path, path_length) &&
VCWD_GETCWD(cwd, MAXPATHLEN)) {
new_state.cwd = estrdup(cwd);
new_state.cwd_length = strlen(cwd);
Expand All @@ -1737,7 +1749,7 @@ CWD_API char *tsrm_realpath(const char *path, char *real_path) /* {{{ */
new_state.cwd_length = 0;
}

if (virtual_file_ex(&new_state, path, NULL, CWD_REALPATH)) {
if (virtual_file_ex(&new_state, path, path_length, NULL, CWD_REALPATH)) {
efree(new_state.cwd);
return NULL;
}
Expand Down
Loading
Loading