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