Page 1 of 1

File search loops on symbolic links

Posted: 2020-11-16, 13:10 UTC
by Dragokas
Hi,

Search results contain:
C:\Users\Alex\Local Settings\Application Data\Application Data\Application Data ...
everything is on the screenshot:

Image: https://ibb.co/myn1xSh

Code: Select all

C:\Users\Alex>dir /a "c:\users\alex\local settings\app*"
 Том в устройстве C имеет метку System
 Серийный номер тома: EA3B-CC12

 Содержимое папки c:\users\alex\local settings

18.04.2018  22:17    <JUNCTION>     Application Data [C:\Users\Alex\AppData\Local]
OS: Windows 7 x64.
TC: v9.51 x64

Thanks for fixing.
Alex.

Re: File search loops on symbolic links

Posted: 2020-11-17, 05:37 UTC
by MVV
It seems that your junction has incorrect permissions, because by default these compatibility links don't allow viewing contents.

Re: File search loops on symbolic links

Posted: 2020-11-17, 15:23 UTC
by ghisler(Author)
Indeed this happens when the permisions are set to allow following the link, but not read the link target. Then TC cannot determine that there is an infinite loop.

Re: File search loops on symbolic links

Posted: 2020-11-18, 08:41 UTC
by MVV
Sometimes I face this problem too, though I'm sure I didn't touch system reparse points.

I think there is a way to reliably detect that folders are the same. You should remember file system indexes for processed folders. If two files or folders have same indexes it is the same file system object. Even if there's no access to problematic junctions themselves, this will help to ignore their subfolders. This code reads file indexes (which are unique per file within a volume) and compares them:

Code: Select all

		wchar_t buf[MAX_PATH];

		ExpandEnvironmentStrings(L"%LOCALAPPDATA%\\GHISLER", buf, ARRAYSIZE(buf));
		HANDLE h1 = CreateFile(buf, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr);
		DWORD e1 = GetLastError();
		BY_HANDLE_FILE_INFORMATION bhfi1;
		GetFileInformationByHandle(h1, &bhfi1);
		CloseHandle(h1);

		ExpandEnvironmentStrings(L"%LOCALAPPDATA%\\Application Data\\GHISLER", buf, ARRAYSIZE(buf));
		HANDLE h2 = CreateFile(buf, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr);
		DWORD e2 = GetLastError();
		BY_HANDLE_FILE_INFORMATION bhfi2;
		GetFileInformationByHandle(h2, &bhfi2);
		CloseHandle(h2);

		bool areSame = bhfi1.nFileIndexLow == bhfi2.nFileIndexLow && bhfi1.nFileIndexHigh == bhfi2.nFileIndexHigh;
Here FILE_FLAG_BACKUP_SEMANTICS flag is required to obtain a directory handle.
You can also compare dwVolumeSerialNumber values to check that two folders are within same volume, but it seems that it is possible for two volumes to have same serial number (it is incorrect and may cause various problems but it is possible).

Perhaps to avoid loops it is enough to keep such "hashes" for folders that form current path, but keeping "hashes" for all processed folders will also allow to ignore folders if they were already accessed via another route.

Re: File search loops on symbolic links

Posted: 2020-11-18, 09:12 UTC
by gdpr deleted 6
Alright, i'll admit ReFS is still (forever? :twisted:) a somewhat exotic file system, but on ReFS the nFileIndexHigh/nFileIndexLow identifier is not guaranteed to be unique (as per official doc: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/ns-fileapi-by_handle_file_information), and GetFileInformationByHandleEx should be used instead to obtain a unique 128-bit file ID. (I am absolutely not sure how probable possible nFileIndexHigh/nFileIndexLow identifier collisions would be on ReFS, though.)

Re: File search loops on symbolic links

Posted: 2020-11-18, 11:51 UTC
by Usher
MVV wrote: 2020-11-18, 08:41 UTCIf two files or folders have same indexes it is the same file system object. Even if there's no access to problematic junctions themselves, this will help to ignore their subfolders. This code reads file indexes (which are unique per file within a volume)
Note that:
1. User made junctions usually redirect to directories on other volumes.
2. You may search all local drives and find files in some directory on volume D:, then search volume Z: and find junction linked to that directory. It may take a long time and the content of the directory may be changed.

Re: File search loops on symbolic links

Posted: 2020-11-23, 09:40 UTC
by MVV
elgonzo,
Thank you for the details regarding Windows servers, I agree that FileId+VolumeSerialNumber from FILE_ID_INFO should be used if available, and nFileIndexHigh+nFileIndexLow+dwVolumeSerialNumber from BY_HANDLE_FILE_INFORMATION otherwise.

Usher,
In case of links to different volumes, such "file id" (consisting of a "file index within a volume" and "volume id") may be used too, for avoiding multiple searches in same folders when there are junctions pointint to the same dir or to a dir and its subdir, Windows will return target volume id in case of a link pointing to another volume.