diff options
Diffstat (limited to 'win/tclWinFile.c')
-rw-r--r-- | win/tclWinFile.c | 81 |
1 files changed, 41 insertions, 40 deletions
diff --git a/win/tclWinFile.c b/win/tclWinFile.c index 700e3c8..333c526 100644 --- a/win/tclWinFile.c +++ b/win/tclWinFile.c @@ -177,7 +177,7 @@ static int WinLink(const TCHAR *LinkSource, const TCHAR *LinkTarget, int linkAction); static int WinSymLinkDirectory(const TCHAR *LinkDirectory, const TCHAR *LinkTarget); -MODULE_SCOPE TCL_NORETURN void tclWinDebugPanic(const char *format, ...); +MODULE_SCOPE void tclWinDebugPanic(const char *format, ...); /* *-------------------------------------------------------------------- @@ -794,7 +794,7 @@ NativeWriteReparse( *---------------------------------------------------------------------- */ -TCL_NORETURN void +void tclWinDebugPanic( const char *format, ...) { @@ -824,16 +824,6 @@ tclWinDebugPanic( MessageBoxW(NULL, msgString, L"Fatal Error", MB_ICONSTOP | MB_OK | MB_TASKMODAL | MB_SETFOREGROUND); } -#if defined(__GNUC__) - __builtin_trap(); -#elif defined(_WIN64) - __debugbreak(); -#elif defined(_MSC_VER) && defined (_M_IX86) - _asm {int 3} -#else - DebugBreak(); -#endif - abort(); } /* @@ -861,15 +851,6 @@ TclpFindExecutable( WCHAR wName[MAX_PATH]; char name[MAX_PATH * TCL_UTF_MAX]; - /* - * Under Windows we ignore argv0, and return the path for the file used to - * create this process. Only if it is NULL, install a new panic handler. - */ - - if (argv0 == NULL) { - Tcl_SetPanicProc(tclWinDebugPanic); - } - #ifdef UNICODE GetModuleFileNameW(NULL, wName, MAX_PATH); #else @@ -1561,11 +1542,12 @@ NativeAccess( return 0; } - if ((mode & W_OK) - && (attr & FILE_ATTRIBUTE_READONLY) - && !(attr & FILE_ATTRIBUTE_DIRECTORY)) { + /* + * If it's not a directory (assume file), do several fast checks: + */ + if (!(attr & FILE_ATTRIBUTE_DIRECTORY)) { /* - * The attributes say the file is not writable. If the file is a + * If the attributes say this is not writable at all. The file is a * regular file (i.e., not a directory), then the file is not * writable, full stop. For directories, the read-only bit is * (mostly) ignored by Windows, so we can't ascertain anything about @@ -1573,21 +1555,38 @@ NativeAccess( * advanced 'getFileSecurityProc', then more robust ACL checks * will be done below. */ + if ((mode & W_OK) && (attr & FILE_ATTRIBUTE_READONLY)) { + Tcl_SetErrno(EACCES); + return -1; + } - Tcl_SetErrno(EACCES); - return -1; - } - - if (mode & X_OK) { - if (!(attr & FILE_ATTRIBUTE_DIRECTORY) && !NativeIsExec(nativePath)) { - /* - * It's not a directory and doesn't have the correct extension. - * Therefore it can't be executable - */ - + /* If doesn't have the correct extension, it can't be executable */ + if ((mode & X_OK) && !NativeIsExec(nativePath)) { Tcl_SetErrno(EACCES); return -1; } + /* Special case for read/write/executable check on file */ + if ((mode & (R_OK|W_OK|X_OK)) && !(mode & ~(R_OK|W_OK|X_OK))) { + DWORD mask = 0; + HANDLE hFile; + if (mode & R_OK) { mask |= GENERIC_READ; } + if (mode & W_OK) { mask |= GENERIC_WRITE; } + if (mode & X_OK) { mask |= GENERIC_EXECUTE; } + + hFile = CreateFile(nativePath, mask, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, + OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, NULL); + if (hFile != INVALID_HANDLE_VALUE) { + CloseHandle(hFile); + return 0; + } + /* fast exit if access was denied */ + if (GetLastError() == ERROR_ACCESS_DENIED) { + Tcl_SetErrno(EACCES); + return -1; + } + } + /* We cannnot verify the access fast, check it below using security info. */ } /* @@ -1792,10 +1791,12 @@ NativeIsExec( return 0; } - if ((_tcsicmp(path+len-3, TEXT("exe")) == 0) - || (_tcsicmp(path+len-3, TEXT("com")) == 0) - || (_tcsicmp(path+len-3, TEXT("cmd")) == 0) - || (_tcsicmp(path+len-3, TEXT("bat")) == 0)) { + path += len-3; + if ((_tcsicmp(path, TEXT("exe")) == 0) + || (_tcsicmp(path, TEXT("com")) == 0) + || (_tcsicmp(path, TEXT("cmd")) == 0) + || (_tcsicmp(path, TEXT("cmd")) == 0) + || (_tcsicmp(path, TEXT("bat")) == 0)) { return 1; } return 0; |