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. */
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 (;;)
{
if (error)
return;
+ sym.pflags |= pflags_or;
+
if (dev.major == DEV_CYGDRIVE_MAJOR)
{
if (!component)
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;
&& 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;
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;
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);
}
-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;
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
{
}
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;
}
}
+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)
{
minor = 0;
pflags &= ~(PATH_SYMLINK | PATH_LNK);
+ unsigned pflags_or = pflags & PATH_NO_ACCESS_CHECK;
case_clash = false;
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;
}
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);
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))
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;
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';
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';
PC_FULL = 0x0010,
PC_NULLEMPTY = 0x0020,
PC_CHECK_EA = 0x0040,
- PC_POSIX = 0x0080
+ PC_POSIX = 0x0080,
+ PC_NO_ACCESS_CHECK = 0x00800000
};
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;