diff options
author | svenbarth <svenbarth@3ad0048d-3df7-0310-abae-a5850022a9f2> | 2020-09-12 08:03:10 +0000 |
---|---|---|
committer | svenbarth <svenbarth@3ad0048d-3df7-0310-abae-a5850022a9f2> | 2020-09-12 08:03:10 +0000 |
commit | 48f090280a350b2f2c89965665e6cce91bbd9dcb (patch) | |
tree | 4d77dd31de190fb535716c8ed55a86d25e8be17d /rtl/win | |
parent | 1fa0c181cd29ab6adb96d1a9f13d74143189c4b0 (diff) | |
download | fpc-48f090280a350b2f2c89965665e6cce91bbd9dcb.tar.gz |
* handle reparse points that are neither symlinks nor mount points as normal files
git-svn-id: https://svn.freepascal.org/svn/fpc/trunk@46855 3ad0048d-3df7-0310-abae-a5850022a9f2
Diffstat (limited to 'rtl/win')
-rw-r--r-- | rtl/win/sysutils.pp | 44 |
1 files changed, 30 insertions, 14 deletions
diff --git a/rtl/win/sysutils.pp b/rtl/win/sysutils.pp index ec36bb4caa..3c1f8eb791 100644 --- a/rtl/win/sysutils.pp +++ b/rtl/win/sysutils.pp @@ -415,7 +415,15 @@ begin end; -function FileGetSymLinkTargetInt(const FileName: UnicodeString; out SymLinkRec: TUnicodeSymLinkRec; RaiseErrorOnMissing: Boolean): Boolean; +type + TSymLinkResult = ( + slrOk, + slrNoSymLink, + slrError + ); + + +function FileGetSymLinkTargetInt(const FileName: UnicodeString; out SymLinkRec: TUnicodeSymLinkRec; RaiseErrorOnMissing: Boolean): TSymLinkResult; { reparse point specific declarations from Windows headers } const IO_REPARSE_TAG_MOUNT_POINT = $A0000003; @@ -451,6 +459,7 @@ var PBuffer: ^TReparseDataBuffer; BytesReturned: DWORD; begin + Result := slrError; SymLinkRec := Default(TUnicodeSymLinkRec); HFile := CreateFileW(PUnicodeChar(FileName), FILE_READ_EA, CShareAny, Nil, OPEN_EXISTING, COpenReparse, 0); @@ -487,8 +496,10 @@ begin raise EDirectoryNotFoundException.Create(SysErrorMessage(GetLastOSError)) else SymLinkRec.TargetName := ''; - end else + end else begin SetLastError(ERROR_REPARSE_TAG_INVALID); + Result := slrNoSymLink; + end; end else SetLastError(ERROR_REPARSE_TAG_INVALID); finally @@ -497,13 +508,15 @@ begin finally CloseHandle(HFile); end; - Result := SymLinkRec.TargetName <> ''; + + if SymLinkRec.TargetName <> '' then + Result := slrOk end; function FileGetSymLinkTarget(const FileName: UnicodeString; out SymLinkRec: TUnicodeSymLinkRec): Boolean; begin - Result := FileGetSymLinkTargetInt(FileName, SymLinkRec, True); + Result := FileGetSymLinkTargetInt(FileName, SymLinkRec, True) = slrOk; end; @@ -526,14 +539,6 @@ const end; end; - function LinkFileExists: Boolean; - var - slr: TUnicodeSymLinkRec; - begin - Result := FileGetSymLinkTargetInt(FileOrDirName, slr, False) and - FileOrDirExists(slr.TargetName, CheckDir, False); - end; - const CNotExistsErrors = [ ERROR_FILE_NOT_FOUND, @@ -548,14 +553,25 @@ const ]; var Attr : DWord; + slr : TUnicodeSymLinkRec; + res : TSymLinkResult; begin Attr := GetFileAttributesW(PUnicodeChar(FileOrDirName)); if Attr = INVALID_FILE_ATTRIBUTES then Result := not (GetLastError in CNotExistsErrors) and FoundByEnum else begin Result := (Attr and FILE_ATTRIBUTE_DIRECTORY) = CDirAttributes[CheckDir]; - if Result and FollowLink and ((Attr and FILE_ATTRIBUTE_REPARSE_POINT) <> 0) then - Result := LinkFileExists; + if Result and FollowLink and ((Attr and FILE_ATTRIBUTE_REPARSE_POINT) <> 0) then begin + res := FileGetSymLinkTargetInt(FileOrDirName, slr, False); + case res of + slrOk: + Result := FileOrDirExists(slr.TargetName, CheckDir, False); + slrNoSymLink: + Result := True; + else + Result := False; + end; + end; end; end; |