diff options
author | Corinna Vinschen <corinna@vinschen.de> | 2017-07-24 18:33:20 +0300 |
---|---|---|
committer | Corinna Vinschen <corinna@vinschen.de> | 2017-07-24 18:33:20 +0300 |
commit | 3e80cefb16cab409c00d5b61be0f7a3befc688e3 (patch) | |
tree | d966684abb04e50270c240d9094826b5e13af8d9 /winsup/cygwin/fhandler_disk_file.cc | |
parent | 42f1be581cdc10438b797c3a5941035a97f01cc4 (diff) |
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>
Diffstat (limited to 'winsup/cygwin/fhandler_disk_file.cc')
-rw-r--r-- | winsup/cygwin/fhandler_disk_file.cc | 67 |
1 files changed, 15 insertions, 52 deletions
diff --git a/winsup/cygwin/fhandler_disk_file.cc b/winsup/cygwin/fhandler_disk_file.cc index 6cc081d98..2144a4cdc 100644 --- a/winsup/cygwin/fhandler_disk_file.cc +++ b/winsup/cygwin/fhandler_disk_file.cc @@ -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; - - if (NT_SUCCESS (NtOpenFile (&reph, READ_CONTROL, attr, &io, - FILE_SHARE_VALID_FLAGS, - FILE_OPEN_FOR_BACKUP_INTENT - | FILE_OPEN_REPARSE_POINT))) - { - 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; - } - } - } + IO_STATUS_BLOCK io; + tmp_pathbuf tp; + UNICODE_STRING symbuf; + bool ret = false; + + 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) tp.c_get (); + ret = (check_reparse_point_target (reph, remote, rp, &symbuf) > 0); NtClose (reph); } return ret; |