]> granicus.if.org Git - php/commitdiff
Revamp unlink() implementation and improve error handling
authorAnatol Belski <ab@php.net>
Thu, 7 Dec 2017 22:05:19 +0000 (23:05 +0100)
committerAnatol Belski <ab@php.net>
Fri, 8 Dec 2017 18:23:18 +0000 (19:23 +0100)
ext/standard/tests/file/unlink_error-win32-mb.phpt
ext/standard/tests/file/unlink_error-win32.phpt
win32/ioutil.c
win32/ioutil.h
win32/winutil.c

index 5111f34b76f7c0eb0ebedcc79c84660926750cb0..4ce4ca796a7ff9836fea2cbed483066c1ef8d1b1 100644 (file)
@@ -108,6 +108,6 @@ bool(false)
 
 -- Testing unlink() on directory --
 
-Warning: unlink(%s/unlink_error): Permission denied in %s on line %d
+Warning: unlink(%s/unlink_error): Is a directory in %s on line %d
 bool(false)
 Done
index e55f6ed5cd48de89b94d6feb6c310a69904535d5..f7a123919ff39218acdc4613db905a30415d2880 100644 (file)
@@ -105,6 +105,6 @@ bool(false)
 
 -- Testing unlink() on directory --
 
-Warning: unlink(%s/unlink_error): Permission denied in %s on line %d
+Warning: unlink(%s/unlink_error): Is a directory in %s on line %d
 bool(false)
 Done
index 68346a19bbe9365b41ca0fd004af79f6d0506031..7f1f75845638968385462dbfbbf3278307471e8b 100644 (file)
@@ -359,16 +359,72 @@ PW32IO int php_win32_ioutil_unlink_w(const wchar_t *path)
 {/*{{{*/
        int ret = 0;
        DWORD err = 0;
+       HANDLE h;
+       BY_HANDLE_FILE_INFORMATION info;
+       FILE_DISPOSITION_INFO disposition;
+       BOOL status;
 
        PHP_WIN32_IOUTIL_CHECK_PATH_W(path, -1, 0)
 
-       if (!DeleteFileW(path)) {
+       h = CreateFileW(path,
+                                       FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES | DELETE,
+                                       PHP_WIN32_IOUTIL_DEFAULT_SHARE_MODE,
+                                       NULL,
+                                       OPEN_EXISTING,
+                                       FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS,
+                                       NULL);
+
+       if (INVALID_HANDLE_VALUE == h) {
                err = GetLastError();
-               ret = -1;
                SET_ERRNO_FROM_WIN32_CODE(err);
+               return -1;
        }
 
-       return ret;
+       if (!GetFileInformationByHandle(h, &info)) {
+               err = GetLastError();
+               CloseHandle(h);
+               SET_ERRNO_FROM_WIN32_CODE(err);
+               return -1;
+       }
+
+       if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
+               /* TODO Handle possible reparse point. */
+               CloseHandle(h);
+               SET_ERRNO_FROM_WIN32_CODE(ERROR_DIRECTORY_NOT_SUPPORTED);
+               return -1;
+       }
+
+#if 0
+       /* XXX BC breach! */
+       if (info.dwFileAttributes & FILE_ATTRIBUTE_READONLY) {
+               /* Remove read-only attribute */
+               FILE_BASIC_INFO basic = { 0 };
+
+               basic.FileAttributes = info.dwFileAttributes & ~(FILE_ATTRIBUTE_READONLY);
+
+               status = SetFileInformationByHandle(h, FileBasicInfo, &basic, sizeof basic);
+               if (!status) {
+                       err = GetLastError();
+                       SET_ERRNO_FROM_WIN32_CODE(err);
+                       CloseHandle(h);
+                       return -1;
+               }
+       }
+#endif
+
+       /* Try to set the delete flag. */
+       disposition.DeleteFile = TRUE;
+       status = SetFileInformationByHandle(h, FileDispositionInfo, &disposition, sizeof disposition);
+       if (!status) {
+               err = GetLastError();
+               CloseHandle(h);
+               SET_ERRNO_FROM_WIN32_CODE(err);
+               return -1;
+       }
+
+       CloseHandle(h);
+
+       return 0;
 }/*}}}*/
 
 PW32IO int php_win32_ioutil_rmdir_w(const wchar_t *path)
index 71737f697b4104746b041bf66c309691db3a605d..5d06fd194082a4667ae07f37a9896a97436c8899 100644 (file)
@@ -241,6 +241,7 @@ PW32IO int php_win32_ioutil_open_w(const wchar_t *path, int flags, ...);
 PW32IO int php_win32_ioutil_chdir_w(const wchar_t *path);
 PW32IO int php_win32_ioutil_rename_w(const wchar_t *oldname, const wchar_t *newname);
 PW32IO wchar_t *php_win32_ioutil_getcwd_w(wchar_t *buf, size_t len);
+PW32IO int php_win32_ioutil_unlink_w(const wchar_t *path);
 
 #if 0
 PW32IO int php_win32_ioutil_mkdir_w(const wchar_t *path, mode_t mode);
@@ -314,19 +315,17 @@ __forceinline static int php_win32_ioutil_open(const char *path, int flags, ...)
 __forceinline static int php_win32_ioutil_unlink(const char *path)
 {/*{{{*/
        PHP_WIN32_IOUTIL_INIT_W(path)
-       int ret = 0;
-       DWORD err = 0;
+       int ret = -1;
+       DWORD err;
 
        if (!pathw) {
                SET_ERRNO_FROM_WIN32_CODE(ERROR_INVALID_PARAMETER);
                return -1;
        }
 
-       PHP_WIN32_IOUTIL_CHECK_PATH_W(pathw, -1, 1)
-
-       if (!DeleteFileW(pathw)) {
+       ret = php_win32_ioutil_unlink_w(pathw);
+       if (0 > ret) {
                err = GetLastError();
-               ret = -1;
        }
        PHP_WIN32_IOUTIL_CLEANUP_W()
 
index 34dda95498fd02bdc1d5f45bf761d545b6096d1f..e1f819ac5e79cd687fa13a44c947287a8c65e855 100644 (file)
@@ -371,6 +371,7 @@ PHP_WINUTIL_API int php_win32_code_to_errno(unsigned long w32Err)
                /* 258 */   ,   { WAIT_TIMEOUT, ETIME}
 
         /* 267 */   ,   {   ERROR_DIRECTORY                 ,   ENOTDIR         }
+               /* 336 */   ,   {   ERROR_DIRECTORY_NOT_SUPPORTED   ,   EISDIR          }
 
         /* 996 */   ,   {   ERROR_IO_INCOMPLETE             ,   EAGAIN          }
         /* 997 */   ,   {   ERROR_IO_PENDING                ,   EAGAIN          }