cygwin: unify reparse point checking code into single function
So far we had two functions checking the content of a reparse point, readdir_check_reparse_point in fhandler_disk_file.cc for the sake of readdir, and symlink_info::check_reparse_point for the sake of generic path checking. * Rename check_reparse_point_target helper to check_reparse_point_string and convert to static function. * Create new check_reparse_point_target helper containing the core reparse point checking code * Just call check_reparse_point_target from readdir_check_reparse_point and symlink_info::check_reparse_point and only perform the unique task in those functions. Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
This commit is contained in:
@ -161,62 +161,25 @@ path_conv::isgood_inode (ino_t ino) const
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Check reparse point to determine if it should be treated as a posix symlink
|
||||
or as a normal file/directory. Mount points are treated as normal directories
|
||||
to match behavior of other systems. Unknown reparse tags are used for
|
||||
things other than links (HSM, compression, dedup), and generally should be
|
||||
treated as a normal file/directory. Native symlinks and mount points are
|
||||
treated as posix symlinks, depending on the prefix of the target name.
|
||||
This logic needs to agree with equivalent logic in path.cc
|
||||
symlink_info::check_reparse_point() .
|
||||
*/
|
||||
/* Check reparse point to determine if it should be treated as a
|
||||
posix symlink or as a normal file/directory. Logic is explained
|
||||
in detail in check_reparse_point_target in path.cc. */
|
||||
static inline bool
|
||||
readdir_check_reparse_point (POBJECT_ATTRIBUTES attr, bool remote)
|
||||
{
|
||||
bool ret = false;
|
||||
IO_STATUS_BLOCK io;
|
||||
NTSTATUS status;
|
||||
HANDLE reph;
|
||||
UNICODE_STRING subst;
|
||||
IO_STATUS_BLOCK io;
|
||||
tmp_pathbuf tp;
|
||||
UNICODE_STRING symbuf;
|
||||
bool ret = false;
|
||||
|
||||
if (NT_SUCCESS (NtOpenFile (&reph, READ_CONTROL, attr, &io,
|
||||
FILE_SHARE_VALID_FLAGS,
|
||||
FILE_OPEN_FOR_BACKUP_INTENT
|
||||
| FILE_OPEN_REPARSE_POINT)))
|
||||
status = NtOpenFile (&reph, READ_CONTROL, attr, &io, FILE_SHARE_VALID_FLAGS,
|
||||
FILE_OPEN_FOR_BACKUP_INTENT | FILE_OPEN_REPARSE_POINT);
|
||||
if (NT_SUCCESS (status))
|
||||
{
|
||||
PREPARSE_DATA_BUFFER rp = (PREPARSE_DATA_BUFFER)
|
||||
alloca (MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
|
||||
if (NT_SUCCESS (NtFsControlFile (reph, NULL, NULL, NULL,
|
||||
&io, FSCTL_GET_REPARSE_POINT, NULL, 0,
|
||||
(LPVOID) rp, MAXIMUM_REPARSE_DATA_BUFFER_SIZE)))
|
||||
{
|
||||
/* If reparse point is stored on a remote volume, lstat returns
|
||||
them as normal files or dirs, not as symlink. For a description,
|
||||
see the comment preceeding remote check in
|
||||
symlink_info::check_reparse_point. */
|
||||
if (!remote && rp->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT)
|
||||
{
|
||||
RtlInitCountedUnicodeString (&subst,
|
||||
(WCHAR *)((char *)rp->MountPointReparseBuffer.PathBuffer
|
||||
+ rp->MountPointReparseBuffer.SubstituteNameOffset),
|
||||
rp->MountPointReparseBuffer.SubstituteNameLength);
|
||||
if (check_reparse_point_target (&subst))
|
||||
ret = true;
|
||||
}
|
||||
else if (rp->ReparseTag == IO_REPARSE_TAG_SYMLINK)
|
||||
{
|
||||
if (rp->SymbolicLinkReparseBuffer.Flags & SYMLINK_FLAG_RELATIVE)
|
||||
ret = true;
|
||||
else
|
||||
{
|
||||
RtlInitCountedUnicodeString (&subst,
|
||||
(WCHAR *)((char *)rp->SymbolicLinkReparseBuffer.PathBuffer
|
||||
+ rp->SymbolicLinkReparseBuffer.SubstituteNameOffset),
|
||||
rp->SymbolicLinkReparseBuffer.SubstituteNameLength);
|
||||
if (check_reparse_point_target (&subst))
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
PREPARSE_DATA_BUFFER rp = (PREPARSE_DATA_BUFFER) tp.c_get ();
|
||||
ret = (check_reparse_point_target (reph, remote, rp, &symbuf) > 0);
|
||||
NtClose (reph);
|
||||
}
|
||||
return ret;
|
||||
|
Reference in New Issue
Block a user