PHP 7.4 INTERNALS UPGRADE NOTES
1. Internal API changes
+ a. php_sys_symlink() and php_sys_link()
2. Build system changes
a. Unix build system changes
1. Internal API changes
========================
+ a. php_sys_symlink() and php_sys_link() portability macros have been
+ added, which behave like POSIX's symlink() and link(), respectively, on
+ POSIX compliant systems and on Windows.
+
========================
2. Build system changes
========================
# define php_sys_stat(path, buf) php_sys_stat_ex(path, buf, 0)
# define php_sys_lstat(path, buf) php_sys_stat_ex(path, buf, 1)
CWD_API ssize_t php_sys_readlink(const char *link, char *target, size_t target_len);
+# define php_sys_symlink php_win32_ioutil_symlink
+# define php_sys_link php_win32_ioutil_link
#else
# define php_sys_stat stat
# define php_sys_lstat lstat
# ifdef HAVE_SYMLINK
# define php_sys_readlink(link, target, target_len) readlink(link, target, target_len)
+# define php_sys_symlink symlink
+# define php_sys_link link
# endif
#endif
/* For the source, an expanded path must be used (in ZTS an other thread could have changed the CWD).
* For the target the exact string given by the user must be used, relative or not, existing or not.
* The target is relative to the link itself, not to the CWD. */
- ret = symlink(topath, source_p);
+ ret = php_sys_symlink(topath, source_p);
if (ret == -1) {
php_error_docref(NULL, E_WARNING, "%s", strerror(errno));
}
#ifndef ZTS
- ret = link(topath, frompath);
+ ret = php_sys_link(topath, frompath);
#else
- ret = link(dest_p, source_p);
+ ret = php_sys_link(dest_p, source_p);
#endif
if (ret == -1) {
php_error_docref(NULL, E_WARNING, "%s", strerror(errno));
/*
TODO:
-- Create php_readlink (done), php_link and php_symlink in win32/link.c
+- Create php_readlink (done), php_link (done) and php_symlink (done) in win32/link.c
- Expose them (PHPAPI) so extensions developers can use them
- define link/readlink/symlink to their php_ equivalent and use them in ext/standart/link.c
- this file is then useless and we have a portable link API
{
char *topath, *frompath;
size_t topath_len, frompath_len;
- BOOLEAN ret;
+ int ret;
char source_p[MAXPATHLEN];
char dest_p[MAXPATHLEN];
char dirname[MAXPATHLEN];
size_t len;
- DWORD attr;
- wchar_t *dstw, *srcw;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "pp", &topath, &topath_len, &frompath, &frompath_len) == FAILURE) {
return;
RETURN_FALSE;
}
- dstw = php_win32_ioutil_any_to_w(topath);
- if (!dstw) {
- php_error_docref(NULL, E_WARNING, "UTF-16 conversion failed (error %d)", GetLastError());
- RETURN_FALSE;
- }
- if ((attr = GetFileAttributesW(dstw)) == INVALID_FILE_ATTRIBUTES) {
- free(dstw);
- php_error_docref(NULL, E_WARNING, "Could not fetch file information(error %d)", GetLastError());
- RETURN_FALSE;
- }
-
- srcw = php_win32_ioutil_any_to_w(source_p);
- if (!srcw) {
- free(dstw);
- php_error_docref(NULL, E_WARNING, "UTF-16 conversion failed (error %d)", GetLastError());
- RETURN_FALSE;
- }
/* For the source, an expanded path must be used (in ZTS an other thread could have changed the CWD).
* For the target the exact string given by the user must be used, relative or not, existing or not.
* The target is relative to the link itself, not to the CWD. */
- ret = CreateSymbolicLinkW(srcw, dstw, (attr & FILE_ATTRIBUTE_DIRECTORY ? 1 : 0));
+ ret = php_sys_symlink(topath, source_p);
- if (!ret) {
- free(dstw);
- free(srcw);
- php_error_docref(NULL, E_WARNING, "Cannot create symlink, error code(%d)", GetLastError());
+ if (ret == -1) {
+ php_error_docref(NULL, E_WARNING, "%s", strerror(errno));
RETURN_FALSE;
}
- free(dstw);
- free(srcw);
-
RETURN_TRUE;
}
/* }}} */
int ret;
char source_p[MAXPATHLEN];
char dest_p[MAXPATHLEN];
- wchar_t *dstw, *srcw;
/*First argument to link function is the target and hence should go to frompath
Second argument to link function is the link itself and hence should go to topath */
}
#ifndef ZTS
-# define _TO_PATH topath
-# define _FROM_PATH frompath
+ ret = php_sys_link(topath, frompath);
#else
-# define _TO_PATH dest_p
-# define _FROM_PATH source_p
+ ret = php_sys_link(dest_p, source_p);
#endif
- dstw = php_win32_ioutil_any_to_w(_TO_PATH);
- if (!dstw) {
- php_error_docref(NULL, E_WARNING, "UTF-16 conversion failed (error %d)", GetLastError());
- RETURN_FALSE;
- }
- srcw = php_win32_ioutil_any_to_w(_FROM_PATH);
- if (!srcw) {
- free(dstw);
- php_error_docref(NULL, E_WARNING, "UTF-16 conversion failed (error %d)", GetLastError());
- RETURN_FALSE;
- }
-#undef _TO_PATH
-#undef _FROM_PATH
-
- ret = CreateHardLinkW(dstw, srcw, NULL);
-
- if (ret == 0) {
- free(dstw);
- free(srcw);
+ if (ret == -1) {
php_error_docref(NULL, E_WARNING, "%s", strerror(errno));
RETURN_FALSE;
}
- free(dstw);
- free(srcw);
-
RETURN_TRUE;
}
/* }}} */
echo "Done\n";
?>
--EXPECTF--
-Warning: symlink(): Could not fetch file information(error 2) in %srename_variation7-win32.php on line %d
+Warning: symlink(): No such file or directory in %srename_variation7-win32.php on line %d
Warning: readlink(): readlink failed to read the symbolic link (%srename_variation7-win32.php.tmp.link), error 2) in %srename_variation7-win32.php on line %d
bool(false)
return php_win32_ioutil_realpath(path, resolved);
}/*}}}*/
+PW32IO int php_win32_ioutil_symlink_w(const wchar_t *target, const wchar_t *link)
+{/*{{{*/
+ DWORD attr;
+ BOOLEAN res;
+
+ if ((attr = GetFileAttributesW(target)) == INVALID_FILE_ATTRIBUTES) {
+ SET_ERRNO_FROM_WIN32_CODE(GetLastError());
+ return -1;
+ }
+
+ res = CreateSymbolicLinkW(link, target, (attr & FILE_ATTRIBUTE_DIRECTORY ? 1 : 0));
+ if (!res) {
+ SET_ERRNO_FROM_WIN32_CODE(GetLastError());
+ return -1;
+ }
+
+ return 0;
+}/*}}}*/
+
+PW32IO int php_win32_ioutil_link_w(const wchar_t *target, const wchar_t *link)
+{/*{{{*/
+ BOOL res;
+
+ res = CreateHardLinkW(target, link, NULL);
+ if (!res) {
+ SET_ERRNO_FROM_WIN32_CODE(GetLastError());
+ return -1;
+ }
+
+ return 0;
+}/*}}}*/
+
/*
* Local variables:
* tab-width: 4
PW32IO FILE *php_win32_ioutil_fopen_w(const wchar_t *path, const wchar_t *mode);
PW32IO wchar_t *php_win32_ioutil_realpath_w(const wchar_t *path, wchar_t *resolved);
PW32IO wchar_t *php_win32_ioutil_realpath_w_ex0(const wchar_t *path, wchar_t *resolved, PBY_HANDLE_FILE_INFORMATION info);
+PW32IO int php_win32_ioutil_symlink_w(const wchar_t *target, const wchar_t *link);
+PW32IO int php_win32_ioutil_link_w(const wchar_t *target, const wchar_t *link);
__forceinline static int php_win32_ioutil_access(const char *path, mode_t mode)
{/*{{{*/
return ret;
}/*}}}*/
+__forceinline static int php_win32_ioutil_symlink(const char *target, const char *link)
+{/*{{{*/
+ wchar_t *targetw, *linkw;
+ int ret;
+
+ targetw = php_win32_ioutil_any_to_w(target);
+ if (!targetw) {
+ SET_ERRNO_FROM_WIN32_CODE(ERROR_INVALID_PARAMETER);
+ return -1;
+ }
+
+ linkw = php_win32_ioutil_any_to_w(link);
+ if (!linkw) {
+ free(targetw);
+ SET_ERRNO_FROM_WIN32_CODE(ERROR_INVALID_PARAMETER);
+ return -1;
+ }
+
+ ret = php_win32_ioutil_symlink_w(targetw, linkw);
+
+ free(targetw);
+ free(linkw);
+
+ return ret;
+}/*}}}*/
+
+__forceinline static int php_win32_ioutil_link(const char *target, const char *link)
+{/*{{{*/
+ wchar_t *targetw, *linkw;
+ int ret;
+
+ targetw = php_win32_ioutil_any_to_w(target);
+ if (!targetw) {
+ SET_ERRNO_FROM_WIN32_CODE(ERROR_INVALID_PARAMETER);
+ return -1;
+ }
+ linkw = php_win32_ioutil_any_to_w(link);
+ if (!linkw) {
+ free(targetw);
+ SET_ERRNO_FROM_WIN32_CODE(ERROR_INVALID_PARAMETER);
+ return -1;
+ }
+
+ ret = php_win32_ioutil_link_w(targetw, linkw);
+
+ free(targetw);
+ free(linkw);
+
+ return ret;
+}/*}}}*/
+
#define HAVE_REALPATH 1
PW32IO char *realpath(const char *path, char *resolved);