From c177980e756d448fb7a9afc9b814fa3da3cc7bb8 Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Tue, 25 Aug 2009 11:27:03 +0000 Subject: [PATCH] * mount.cc (fs_info::update): Add comment. * path.cc (symlink_info::check_reparse_point): Return -1 for volume mount points. Explain why. (symlink_info::check): Call fs.update again for volume mount points. Explain why. --- winsup/cygwin/ChangeLog | 8 ++++++++ winsup/cygwin/mount.cc | 3 +++ winsup/cygwin/path.cc | 18 +++++++++++++++--- 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index fbfa72c11..53906bc8f 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,11 @@ +2009-08-24 Corinna Vinschen + + * mount.cc (fs_info::update): Add comment. + * path.cc (symlink_info::check_reparse_point): Return -1 for volume + mount points. Explain why. + (symlink_info::check): Call fs.update again for volume mount points. + Explain why. + 2009-08-24 Corinna Vinschen * globals.cc (ro_u_volume): New R/O unicode string. diff --git a/winsup/cygwin/mount.cc b/winsup/cygwin/mount.cc index b5c548d95..a0b4b6782 100644 --- a/winsup/cygwin/mount.cc +++ b/winsup/cygwin/mount.cc @@ -134,6 +134,9 @@ fs_info::update (PUNICODE_STRING upath, HANDLE in_vol) /* Always caseinsensitive. We really just need access to the drive. */ InitializeObjectAttributes (&attr, upath, OBJ_CASE_INSENSITIVE, NULL, NULL); + /* Note: Don't use the FILE_OPEN_REPARSE_POINT flag here. The reason + is that symlink_info::check relies on being able to open a handle + to the target of a volume mount point. */ status = NtOpenFile (&vol, access, &attr, &io, FILE_SHARE_VALID_FLAGS, FILE_OPEN_FOR_BACKUP_INTENT); /* At least one filesystem (HGFS, VMware shared folders) doesn't like diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc index e6782f6e9..4d0b1b9d2 100644 --- a/winsup/cygwin/path.cc +++ b/winsup/cygwin/path.cc @@ -1874,8 +1874,10 @@ symlink_info::check_reparse_point (HANDLE h) if (rp->MountPointReparseBuffer.PrintNameLength == 0 || RtlEqualUnicodePathPrefix (&subst, &ro_u_volume, TRUE)) { - /* Volume mount point. Not treated as symlink. */ - return 0; + /* Volume mount point. Not treated as symlink. The return + value of -1 is a hint for the caller to treat this as a + volume mount point. */ + return -1; } sys_wcstombs (srcbuf, SYMLINK_MAX + 1, (WCHAR *)((char *)rp->MountPointReparseBuffer.PathBuffer @@ -2410,7 +2412,17 @@ symlink_info::check (char *path, const suffix_info *suffixes, unsigned opt, else if (fileattr & FILE_ATTRIBUTE_REPARSE_POINT) { res = check_reparse_point (h); - if (res) + if (res == -1) + { + /* Volume mount point. The filesystem information for the top + level directory should be for the volume top level directory + itself, rather than for the reparse point itself. So we + fetch the filesystem information again, but with a NULL + handle. This does what we want because fs_info::update opens + the handle without FILE_OPEN_REPARSE_POINT. */ + fs.update (&upath, NULL); + } + else if (res) break; }