readdir() with mount point dentry, return mount point INO
This patch fixes a minor compatibility issue w/ cygwin mount point handling in readdir(), compared to equivalent behavior of Linux and MacOS. dentry.d_ino should indicate the INO of the mount point itself, not the target volume root folder. Changed return type from readdir_check_reparse_point to uint8_t, to avoid unnecessarily being implicitly cast to and from a signed int. Renamed a related local variable "attr" to "oattr" that was eclipsing a member variable with the same name. Joe L.
This commit is contained in:
		
				
					committed by
					
						 Corinna Vinschen
						Corinna Vinschen
					
				
			
			
				
	
			
			
			
						parent
						
							35cd6863fb
						
					
				
				
					commit
					0a9edd73e3
				
			| @@ -178,10 +178,10 @@ path_conv::isgood_inode (ino_t ino) const | |||||||
|    are directory mount points, which are treated as symlinks. |    are directory mount points, which are treated as symlinks. | ||||||
|    IO_REPARSE_TAG_SYMLINK types are always symlinks.  We don't know |    IO_REPARSE_TAG_SYMLINK types are always symlinks.  We don't know | ||||||
|    anything about other reparse points, so they are treated as unknown.  */ |    anything about other reparse points, so they are treated as unknown.  */ | ||||||
| static inline int | static inline uint8_t | ||||||
| readdir_check_reparse_point (POBJECT_ATTRIBUTES attr) | readdir_check_reparse_point (POBJECT_ATTRIBUTES attr) | ||||||
| { | { | ||||||
|   DWORD ret = DT_UNKNOWN; |   uint8_t ret = DT_UNKNOWN; | ||||||
|   IO_STATUS_BLOCK io; |   IO_STATUS_BLOCK io; | ||||||
|   HANDLE reph; |   HANDLE reph; | ||||||
|   UNICODE_STRING subst; |   UNICODE_STRING subst; | ||||||
| @@ -2016,32 +2016,19 @@ fhandler_disk_file::readdir_helper (DIR *dir, dirent *de, DWORD w32_err, | |||||||
| 	de->d_type = DT_REG; | 	de->d_type = DT_REG; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   /* Check for directory reparse point.  These are potential volume mount |   /* Check for directory reparse point. These may be treated as a posix | ||||||
|      points which have another inode than the underlying directory. */ |      symlink, or as mount point, so need to figure out whether to return | ||||||
|  |      a directory or link type. In all cases, returning the INO of the | ||||||
|  |      reparse point (not of the target) matches behavior of posix systems. | ||||||
|  |      */ | ||||||
|   if ((attr & (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT)) |   if ((attr & (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT)) | ||||||
|       == (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT)) |       == (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT)) | ||||||
|     { |     { | ||||||
|       HANDLE reph; |       OBJECT_ATTRIBUTES oattr; | ||||||
|       OBJECT_ATTRIBUTES attr; |  | ||||||
|       IO_STATUS_BLOCK io; |  | ||||||
|  |  | ||||||
|       InitializeObjectAttributes (&attr, fname, pc.objcaseinsensitive (), |       InitializeObjectAttributes (&oattr, fname, pc.objcaseinsensitive (), | ||||||
| 				  get_handle (), NULL); | 				  get_handle (), NULL); | ||||||
|       de->d_type = readdir_check_reparse_point (&attr); |       de->d_type = readdir_check_reparse_point (&oattr); | ||||||
|       if (de->d_type == DT_DIR) |  | ||||||
| 	{ |  | ||||||
| 	  /* Volume mountpoints are treated as directories.  We have to fix |  | ||||||
| 	     the inode number, otherwise we have the inode number of the |  | ||||||
| 	     mount point, rather than the inode number of the toplevel |  | ||||||
| 	     directory of the mounted drive. */ |  | ||||||
| 	  if (NT_SUCCESS (NtOpenFile (&reph, READ_CONTROL, &attr, &io, |  | ||||||
| 				      FILE_SHARE_VALID_FLAGS, |  | ||||||
| 				      FILE_OPEN_FOR_BACKUP_INTENT))) |  | ||||||
| 	    { |  | ||||||
| 	      de->d_ino = pc.get_ino_by_handle (reph); |  | ||||||
| 	      NtClose (reph); |  | ||||||
| 	    } |  | ||||||
| 	} |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   /* Check for Windows shortcut. If it's a Cygwin or U/WIN symlink, drop the |   /* Check for Windows shortcut. If it's a Cygwin or U/WIN symlink, drop the | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user