diff options
| author | dkf <donal.k.fellows@manchester.ac.uk> | 2018-05-05 17:30:52 (GMT) |
|---|---|---|
| committer | dkf <donal.k.fellows@manchester.ac.uk> | 2018-05-05 17:30:52 (GMT) |
| commit | 411bfad9f4e43665addd2312735cc591dc8520f9 (patch) | |
| tree | 6ef4441753da8b4942f136ede5367572bca581a7 /win/tclWinFile.c | |
| parent | f58e9ed8421d4020d88ac31edc1e1954fd7838c4 (diff) | |
| parent | 215b091d17a465decdc7abfdb701588f31db8714 (diff) | |
| download | tcl-411bfad9f4e43665addd2312735cc591dc8520f9.zip tcl-411bfad9f4e43665addd2312735cc591dc8520f9.tar.gz tcl-411bfad9f4e43665addd2312735cc591dc8520f9.tar.bz2 | |
merge 8.7
Diffstat (limited to 'win/tclWinFile.c')
| -rw-r--r-- | win/tclWinFile.c | 58 |
1 files changed, 39 insertions, 19 deletions
diff --git a/win/tclWinFile.c b/win/tclWinFile.c index 700e3c8..7693f06 100644 --- a/win/tclWinFile.c +++ b/win/tclWinFile.c @@ -1561,11 +1561,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 +1574,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 +1810,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; |
