From 0d4ebb2ba7169c9412be47429b698f2288539647 Mon Sep 17 00:00:00 2001 From: cgf Date: Sat, 12 Mar 2005 02:32:58 +0000 Subject: [PATCH] * path.h (pathconv_arg): Define PC_NO_ACCESS_CHECK. (path_types): Define PATH_NO_ACCESS_CHECK == PC_NO_ACCESS_CHECK. * path.cc (symlink_info::check_sysfile): Move to symlink_info class and eliminate arguments that are part of class. Use set_error. (symlink_info::check_shortcut): Ditto. (symlink_info::set_error): New function. (path_conv::check): Pass PC_NO_ACCESS_CHECK to symlink_info::check. (symlink_info::check): Preserve PC_NO_ACCESS_CHECK in pflags. Use set_error. --- winsup/cygwin/ChangeLog | 12 ++++++++++ winsup/cygwin/path.cc | 63 +++++++++++++++++++++++++++++-------------------- winsup/cygwin/path.h | 28 ++++++++++++---------- 3 files changed, 65 insertions(+), 38 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index c0ae04f9d6..5916f0bb2f 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,15 @@ +2005-03-11 Christopher Faylor + + * path.h (pathconv_arg): Define PC_NO_ACCESS_CHECK. + (path_types): Define PATH_NO_ACCESS_CHECK == PC_NO_ACCESS_CHECK. + * path.cc (symlink_info::check_sysfile): Move to symlink_info class and + eliminate arguments that are part of class. Use set_error. + (symlink_info::check_shortcut): Ditto. + (symlink_info::set_error): New function. + (path_conv::check): Pass PC_NO_ACCESS_CHECK to symlink_info::check. + (symlink_info::check): Preserve PC_NO_ACCESS_CHECK in pflags. Use + set_error. + 2005-03-10 Corinna Vinschen * path.cc (is_floppy): New function. diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc index 151c8ea821..5276796dfb 100644 --- a/winsup/cygwin/path.cc +++ b/winsup/cygwin/path.cc @@ -99,6 +99,9 @@ struct symlink_info int set (char *path); bool parse_device (const char *); bool case_check (char *path); + int check_sysfile (const char *path, HANDLE h); + int check_shortcut (const char *path, HANDLE h); + void set_error (int); }; int pcheck_case = PCHECK_RELAXED; /* Determines the case check behaviour. */ @@ -544,6 +547,7 @@ path_conv::check (const char *src, unsigned opt, error = 0; else if ((error = check_null_empty_str (src))) return; + unsigned pflags_or = (opt & PC_NO_ACCESS_CHECK); /* This loop handles symlink expansion. */ for (;;) { @@ -603,6 +607,8 @@ path_conv::check (const char *src, unsigned opt, if (error) return; + sym.pflags |= pflags_or; + if (dev.major == DEV_CYGDRIVE_MAJOR) { if (!component) @@ -767,7 +773,7 @@ is_virtual_symlink: else break; } - else if (sym.error != ENOENT && sym.error != ENOSHARE) /* E. g. EACCES */ + else if (sym.error != ENOENT && sym.error != ENOSHARE) { error = sym.error; goto out; @@ -2776,9 +2782,8 @@ cmp_shortcut_header (win_shortcut_hdr *file_header) && file_header->run == SW_NORMAL; } -static int -check_shortcut (const char *path, DWORD fileattr, HANDLE h, - char *contents, int *error, unsigned *pflags) +int +symlink_info::check_shortcut (const char *path, HANDLE h) { win_shortcut_hdr *file_header; char *buf, *cp; @@ -2795,7 +2800,7 @@ check_shortcut (const char *path, DWORD fileattr, HANDLE h, buf = (char *) alloca (size); if (!ReadFile (h, buf, size, &got, 0)) { - *error = EIO; + set_error (EIO); goto close_it; } file_header = (win_shortcut_hdr *) buf; @@ -2810,13 +2815,13 @@ check_shortcut (const char *path, DWORD fileattr, HANDLE h, contents[len] = '\0'; res = len; if (res) /* It's a symlink. */ - *pflags = PATH_SYMLINK | PATH_LNK; + pflags = PATH_SYMLINK | PATH_LNK; goto close_it; file_not_symlink: /* Not a symlink, see if executable. */ - if (!(*pflags & PATH_ALL_EXEC) && has_exec_chars ((const char *) &file_header, got)) - *pflags |= PATH_EXEC; + if (!(pflags & PATH_ALL_EXEC) && has_exec_chars ((const char *) &file_header, got)) + pflags |= PATH_EXEC; close_it: CloseHandle (h); @@ -2824,9 +2829,8 @@ close_it: } -static int -check_sysfile (const char *path, DWORD fileattr, HANDLE h, - char *contents, int *error, unsigned *pflags) +int +symlink_info::check_sysfile (const char *path, HANDLE h) { char cookie_buf[sizeof (SYMLINK_COOKIE) - 1]; DWORD got; @@ -2835,19 +2839,19 @@ check_sysfile (const char *path, DWORD fileattr, HANDLE h, if (!ReadFile (h, cookie_buf, sizeof (cookie_buf), &got, 0)) { debug_printf ("ReadFile1 failed"); - *error = EIO; + set_error (EIO); } else if (got == sizeof (cookie_buf) && memcmp (cookie_buf, SYMLINK_COOKIE, sizeof (cookie_buf)) == 0) { /* It's a symlink. */ - *pflags = PATH_SYMLINK; + pflags = PATH_SYMLINK; res = ReadFile (h, contents, CYG_MAX_PATH + 1, &got, 0); if (!res) { debug_printf ("ReadFile2 failed"); - *error = EIO; + set_error (EIO); } else { @@ -2866,19 +2870,19 @@ check_sysfile (const char *path, DWORD fileattr, HANDLE h, } else if (got == sizeof (cookie_buf) && memcmp (cookie_buf, SOCKET_COOKIE, sizeof (cookie_buf)) == 0) - *pflags |= PATH_SOCKET; + pflags |= PATH_SOCKET; else { /* Not a symlink, see if executable. */ - if (*pflags & PATH_ALL_EXEC) + if (pflags & PATH_ALL_EXEC) /* Nothing to do */; else if (has_exec_chars (cookie_buf, got)) - *pflags |= PATH_EXEC; + pflags |= PATH_EXEC; else - *pflags |= PATH_NOTEXEC; + pflags |= PATH_NOTEXEC; } syscall_printf ("%d = symlink.check_sysfile (%s, %s) (%p)", - res, path, contents, *pflags); + res, path, contents, pflags); CloseHandle (h); return res; @@ -3001,6 +3005,14 @@ suffix_scan::next () } } +void +symlink_info::set_error (int in_errno) +{ + if ((pflags & PATH_NO_ACCESS_CHECK) && in_errno != ENAMETOOLONG) + return; + error = in_errno; +} + bool symlink_info::parse_device (const char *contents) { @@ -3075,6 +3087,7 @@ symlink_info::check (char *path, const suffix_info *suffixes, unsigned opt) minor = 0; pflags &= ~(PATH_SYMLINK | PATH_LNK); + unsigned pflags_or = pflags & PATH_NO_ACCESS_CHECK; case_clash = false; @@ -3088,7 +3101,7 @@ symlink_info::check (char *path, const suffix_info *suffixes, unsigned opt) matter, so we just return 0. For example, getting the attributes of \\HOST will typically fail. */ debug_printf ("GetFileAttributes (%s) failed", suffix.path); - error = geterrno_from_win_error (GetLastError (), EACCES); + set_error (geterrno_from_win_error (GetLastError (), EACCES)); continue; } @@ -3122,7 +3135,7 @@ symlink_info::check (char *path, const suffix_info *suffixes, unsigned opt) if (sym_check > 0 && opt & PC_CHECK_EA && (res = get_symlink_ea (suffix.path, contents, sizeof (contents))) > 0) { - pflags = PATH_SYMLINK; + pflags = PATH_SYMLINK | pflags_or; if (sym_check == 1) pflags |= PATH_LNK; debug_printf ("Got symlink from EA: %s", contents); @@ -3142,7 +3155,7 @@ symlink_info::check (char *path, const suffix_info *suffixes, unsigned opt) switch (sym_check) { case 1: - res = check_shortcut (suffix.path, fileattr, h, contents, &error, &pflags); + res = check_shortcut (suffix.path, h); if (!res) /* check more below */; else if (contents[0] == ':' && contents[1] == '\\' && parse_device (contents)) @@ -3157,7 +3170,7 @@ symlink_info::check (char *path, const suffix_info *suffixes, unsigned opt) fileattr = INVALID_FILE_ATTRIBUTES; continue; /* in case we're going to tack *another* .lnk on this filename. */ case 2: - res = check_sysfile (suffix.path, fileattr, h, contents, &error, &pflags); + res = check_sysfile (suffix.path, h); if (!res) goto file_not_symlink; break; @@ -3453,7 +3466,7 @@ fchdir (int fd) extern "C" int cygwin_conv_to_win32_path (const char *path, char *win32_path) { - path_conv p (path, PC_SYM_FOLLOW); + path_conv p (path, PC_SYM_FOLLOW | PC_NO_ACCESS_CHECK); if (p.error) { win32_path[0] = '\0'; @@ -3468,7 +3481,7 @@ cygwin_conv_to_win32_path (const char *path, char *win32_path) extern "C" int cygwin_conv_to_full_win32_path (const char *path, char *win32_path) { - path_conv p (path, PC_SYM_FOLLOW | PC_FULL); + path_conv p (path, PC_SYM_FOLLOW | PC_FULL | PC_NO_ACCESS_CHECK); if (p.error) { win32_path[0] = '\0'; diff --git a/winsup/cygwin/path.h b/winsup/cygwin/path.h index 171f510e98..e0a565fc18 100644 --- a/winsup/cygwin/path.h +++ b/winsup/cygwin/path.h @@ -38,7 +38,8 @@ enum pathconv_arg PC_FULL = 0x0010, PC_NULLEMPTY = 0x0020, PC_CHECK_EA = 0x0040, - PC_POSIX = 0x0080 + PC_POSIX = 0x0080, + PC_NO_ACCESS_CHECK = 0x00800000 }; enum case_checking @@ -54,18 +55,19 @@ enum case_checking enum path_types { - PATH_NOTHING = 0, - PATH_SYMLINK = MOUNT_SYMLINK, - PATH_BINARY = MOUNT_BINARY, - PATH_EXEC = MOUNT_EXEC, - PATH_NOTEXEC = MOUNT_NOTEXEC, - PATH_CYGWIN_EXEC = MOUNT_CYGWIN_EXEC, - PATH_ENC = MOUNT_ENC, - PATH_ALL_EXEC = (PATH_CYGWIN_EXEC | PATH_EXEC), - PATH_LNK = 0x01000000, - PATH_TEXT = 0x02000000, - PATH_HAS_SYMLINKS = 0x10000000, - PATH_SOCKET = 0x40000000 + PATH_NOTHING = 0, + PATH_SYMLINK = MOUNT_SYMLINK, + PATH_BINARY = MOUNT_BINARY, + PATH_EXEC = MOUNT_EXEC, + PATH_NOTEXEC = MOUNT_NOTEXEC, + PATH_CYGWIN_EXEC = MOUNT_CYGWIN_EXEC, + PATH_ENC = MOUNT_ENC, + PATH_ALL_EXEC = (PATH_CYGWIN_EXEC | PATH_EXEC), + PATH_NO_ACCESS_CHECK = PC_NO_ACCESS_CHECK, + PATH_LNK = 0x01000000, + PATH_TEXT = 0x02000000, + PATH_HAS_SYMLINKS = 0x10000000, + PATH_SOCKET = 0x40000000 }; class symlink_info; -- 2.11.0