summaryrefslogtreecommitdiffstats
path: root/winsup/cygwin/path.cc
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/cygwin/path.cc')
-rw-r--r--winsup/cygwin/path.cc70
1 files changed, 59 insertions, 11 deletions
diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc
index fe81acd8b..4b8179c8e 100644
--- a/winsup/cygwin/path.cc
+++ b/winsup/cygwin/path.cc
@@ -761,8 +761,8 @@ path_conv::check (const char *src, unsigned opt,
{
/* FIXME: Calling build_fhandler here is not the right way to handle this. */
fhandler_virtual *fh = (fhandler_virtual *) build_fh_dev (dev, path_copy);
- int file_type = fh->exists ();
- if (file_type == -2)
+ virtual_ftype_t file_type = fh->exists ();
+ if (file_type == virt_symlink)
{
fh->fill_filebuf ();
symlen = sym.set (fh->get_filebuf ());
@@ -770,31 +770,61 @@ path_conv::check (const char *src, unsigned opt,
delete fh;
switch (file_type)
{
- case 1:
- case 2:
+ case virt_directory:
+ case virt_rootdir:
if (component == 0)
fileattr = FILE_ATTRIBUTE_DIRECTORY;
break;
- case -1:
+ case virt_file:
if (component == 0)
fileattr = 0;
break;
- case -2: /* /proc/self or /proc/<pid>/symlinks */
+ case virt_symlink:
goto is_virtual_symlink;
- case -3: /* /proc/<pid>/fd/pipe:[] */
+ case virt_pipe:
if (component == 0)
{
fileattr = 0;
dev.parse (FH_PIPE);
}
break;
- case -4: /* /proc/<pid>/fd/socket:[] */
+ case virt_socket:
if (component == 0)
{
fileattr = 0;
dev.parse (FH_TCP);
}
break;
+ case virt_fsdir:
+ case virt_fsfile:
+ /* Access to real file or directory via block device
+ entry in /proc/sys. Convert to real file and go with
+ the flow. */
+ dev.parse (FH_FS);
+ goto is_fs_via_procsys;
+ case virt_blk:
+ /* Block special device. If the trailing slash has been
+ requested, the target is the root directory of the
+ filesystem on this block device. So we convert this to
+ a real file and attach the backslash. */
+ if (component || need_directory)
+ {
+ dev.parse (FH_FS);
+ if (component == 0)
+ {
+ strcat (full_path, "\\");
+ fileattr = FILE_ATTRIBUTE_DIRECTORY
+ | FILE_ATTRIBUTE_DEVICE;
+ }
+ else
+ fileattr = 0;
+ goto out;
+ }
+ /*FALLTHRU*/
+ case virt_chr:
+ if (component == 0)
+ fileattr = FILE_ATTRIBUTE_DEVICE;
+ break;
default:
if (component == 0)
fileattr = INVALID_FILE_ATTRIBUTES;
@@ -841,6 +871,8 @@ path_conv::check (const char *src, unsigned opt,
if (is_msdos)
sym.pflags |= PATH_NOPOSIX | PATH_NOACL;
+is_fs_via_procsys:
+
symlen = sym.check (full_path, suff, fs, conv_handle);
is_virtual_symlink:
@@ -2850,6 +2882,14 @@ cygwin_conv_path (cygwin_conv_path_t what, const void *from, void *to,
if (buf[1] != ':') /* native UNC path */
*(buf += 2) = '\\';
}
+ else if (*buf == '\\')
+ {
+ /* Device name points to somewhere else in the NT namespace.
+ Use GLOBALROOT prefix to convert to Win32 path. */
+ char *p = stpcpy (buf, "\\\\.\\GLOBALROOT");
+ sys_wcstombs (p, NT_MAX_PATH - (p - buf),
+ up->Buffer, up->Length / sizeof (WCHAR));
+ }
lsiz = strlen (buf) + 1;
/* TODO: Incoming "." is a special case which leads to a trailing
backslash ".\\" in the Win32 path. That's a result of the
@@ -2891,7 +2931,8 @@ cygwin_conv_path (cygwin_conv_path_t what, const void *from, void *to,
quite a bunch of Win32 functions, especially in user32.dll,
apparently, which don't grok long path names at all, not even
in the UNICODE API. */
- if (lsiz <= MAX_PATH + 4 || (path[5] != L':' && lsiz <= MAX_PATH + 6))
+ if ((path[5] == L':' && lsiz <= MAX_PATH + 4)
+ || (!wcsncmp (path + 4, L"UNC\\", 4) && lsiz <= MAX_PATH + 6))
{
path += 4;
lsiz -= 4;
@@ -2902,6 +2943,13 @@ cygwin_conv_path (cygwin_conv_path_t what, const void *from, void *to,
}
}
}
+ else if (*path == L'\\')
+ {
+ /* Device name points to somewhere else in the NT namespace.
+ Use GLOBALROOT prefix to convert to Win32 path. */
+ to = (void *) wcpcpy ((wchar_t *) to, L"\\\\.\\GLOBALROOT");
+ lsiz += sizeof ("\\\\.\\GLOBALROOT") - 1;
+ }
/* TODO: Same ".\\" band-aid as in CCP_POSIX_TO_WIN_A case. */
if (relative && !strcmp ((const char *) from, ".")
&& !wcscmp (path, L".\\"))
@@ -2943,10 +2991,10 @@ cygwin_conv_path (cygwin_conv_path_t what, const void *from, void *to,
case CCP_POSIX_TO_WIN_A:
case CCP_WIN_A_TO_POSIX:
case CCP_WIN_W_TO_POSIX:
- strcpy ((char *) to, buf);
+ stpcpy ((char *) to, buf);
break;
case CCP_POSIX_TO_WIN_W:
- wcscpy ((PWCHAR) to, path);
+ wcpcpy ((PWCHAR) to, path);
break;
}
return 0;