From 30cf835f7e12552bac12eb1cd9123febe909d6e2 Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Sun, 10 Dec 2006 12:56:50 +0000 Subject: [PATCH] * fhandler.cc (rootdir): Drop useless post-increment. Take volume mount points into account. (check_posix_perm): Allocate space for root directory big enough. --- winsup/cygwin/ChangeLog | 6 ++++ winsup/cygwin/fhandler.cc | 58 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 62 insertions(+), 2 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 2be62f2f3..d9faceb85 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,9 @@ +2006-12-10 Corinna Vinschen + + * fhandler.cc (rootdir): Drop useless post-increment. Take volume + mount points into account. + (check_posix_perm): Allocate space for root directory big enough. + 2006-12-09 Corinna Vinschen * syscalls.cc (try_to_bin): Add comment that this is not possibly diff --git a/winsup/cygwin/fhandler.cc b/winsup/cygwin/fhandler.cc index 0fc9e6fcc..03dc0b803 100644 --- a/winsup/cygwin/fhandler.cc +++ b/winsup/cygwin/fhandler.cc @@ -1221,7 +1221,7 @@ rootdir (const char *full_path, char *root_path) if (full_path[1] == ':') { - *rootp++ = *full_path++; + *rootp++ = *full_path; *rootp++ = ':'; } else if (full_path[0] == '\\' && full_path[1] == '\\') @@ -1239,6 +1239,60 @@ rootdir (const char *full_path, char *root_path) *rootp++ = '\\'; *rootp = '\0'; + + /* This also determines whether reparse points are available. */ + if (!wincap.has_guid_volumes ()) + return root_path; + + PREPARSE_DATA_BUFFER rp = (PREPARSE_DATA_BUFFER) + alloca (MAXIMUM_REPARSE_DATA_BUFFER_SIZE); + + char *test_path = (char *) alloca (CYG_MAX_PATH); + strcpy (test_path, full_path); + + /* This determines the minimum length of the path we test for mount points. + If we're below this value, it's the root dir of the path itself. */ + char *min_c = test_path + (rootp - root_path); + char *c = min_c; + while (*c) + ++c; + while (c > min_c) + { + *c = '\0'; + +# define MOUNTPT_ATTR (FILE_ATTRIBUTE_DIRECTORY \ + | FILE_ATTRIBUTE_REPARSE_POINT) + DWORD attr = GetFileAttributes (test_path); + if (attr != INVALID_FILE_ATTRIBUTES + && (attr & MOUNTPT_ATTR) == MOUNTPT_ATTR) + { + HANDLE h = CreateFile (test_path, GENERIC_READ, FILE_SHARE_READ, + &sec_none_nih, OPEN_EXISTING, + FILE_FLAG_OPEN_REPARSE_POINT + | FILE_FLAG_BACKUP_SEMANTICS, NULL); + if (h != INVALID_HANDLE_VALUE) + { + DWORD size; + BOOL ret = DeviceIoControl (h, FSCTL_GET_REPARSE_POINT, NULL, + 0, (LPVOID) rp, + MAXIMUM_REPARSE_DATA_BUFFER_SIZE, + &size, NULL); + CloseHandle (h); + if (ret + && rp->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT + && !rp->SymbolicLinkReparseBuffer.PrintNameLength) + { + memcpy (root_path, test_path, len = c - test_path); + strcpy (root_path + len, "\\"); + CloseHandle (h); + break; + } + } + } + while (--c > min_c && *c != '\\') + ; + } + return root_path; } @@ -1739,7 +1793,7 @@ check_posix_perm (const char *fname, int v) if (!allow_ntsec) return 0; - char *root = rootdir (fname, (char *)alloca (strlen (fname))); + char *root = rootdir (fname, (char *)alloca (strlen (fname) + 2)); if (!allow_smbntsec && ((root[0] == '\\' && root[1] == '\\')