Revamp unlink() implementation and improve error handling

This commit is contained in:
Anatol Belski 2017-12-07 23:05:19 +01:00
parent 17d621e7d3
commit 2fbdaec03c
5 changed files with 67 additions and 11 deletions

View 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

View 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

View 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)

View 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()

View 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 }