]> granicus.if.org Git - php/commitdiff
Create and expose php_sys_symlink() and php_sys_link()
authorChristoph M. Becker <cmbecker69@gmx.de>
Thu, 2 Aug 2018 12:08:30 +0000 (14:08 +0200)
committerChristoph M. Becker <cmbecker69@gmx.de>
Thu, 2 Aug 2018 12:08:30 +0000 (14:08 +0200)
These macros are supposed to behave like POSIX's symlink() and link(),
respectively, on POSIX compliant systems and on Windows.

Future scope: merge link.c and link_win32.c

UPGRADING.INTERNALS
Zend/zend_virtual_cwd.h
ext/standard/link.c
ext/standard/link_win32.c
ext/standard/tests/file/rename_variation7-win32.phpt
win32/ioutil.c
win32/ioutil.h

index 32f043b55fec83303ada593be167c50b509e87c4..b949e78803401b765c1cddd1a5225b894354100d 100644 (file)
@@ -1,6 +1,7 @@
 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
@@ -12,6 +13,10 @@ PHP 7.4 INTERNALS UPGRADE NOTES
 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
 ========================
index 43d3965adb65b4c1252a9465ec7f3fd13937e275..feee04a745ab01fbfc2a8bef33f2199f1d14c4c9 100644 (file)
@@ -120,11 +120,15 @@ CWD_API int php_sys_stat_ex(const char *path, zend_stat_t *buf, int lstat);
 # 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
 
index 5ca8b2c49c8576da906b939587823384e8c2143d..c95c75d136bcdaf761199710275b2f06613ade11 100644 (file)
@@ -160,7 +160,7 @@ PHP_FUNCTION(symlink)
        /* 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));
@@ -207,9 +207,9 @@ PHP_FUNCTION(link)
        }
 
 #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));
index ae6cdd11f2ce404609e6d36379bc4079ce3c526c..bc9931359db5395f0523801c2ebe7b9ba37e0262 100644 (file)
@@ -43,7 +43,7 @@
 
 /*
 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
@@ -122,13 +122,11 @@ PHP_FUNCTION(symlink)
 {
        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;
@@ -162,38 +160,16 @@ PHP_FUNCTION(symlink)
                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;
 }
 /* }}} */
@@ -207,7 +183,6 @@ PHP_FUNCTION(link)
        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 */
@@ -236,38 +211,15 @@ PHP_FUNCTION(link)
        }
 
 #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;
 }
 /* }}} */
index 369e8c2d43b28d38384e84c436af72982f6527fa..b1a04b38c62c0a0ee4ca5433d8550f7eea1ee5bc 100644 (file)
@@ -26,7 +26,7 @@ var_dump(readlink($tmp_link2));
 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)
index 2ff62e3b6ce9b3ea243355fe76e17fc533e1960d..d3fb2bdb59d81c2ccca4b6e9a9e7491f24e539db 100644 (file)
@@ -785,6 +785,38 @@ PW32IO char *realpath(const char *path, char *resolved)
        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
index 2a396f67b617a596f75b6c4eb8fc8f1114288811..8c0275cad61ffdfd40c42a2b6514f495e217f9e9 100644 (file)
@@ -261,6 +261,8 @@ PW32IO int php_win32_ioutil_mkdir_w(const wchar_t *path, mode_t mode);
 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)
 {/*{{{*/
@@ -571,6 +573,57 @@ __forceinline static int php_win32_ioutil_mkdir(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);