summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--winsup/cygwin/mount.cc20
-rw-r--r--winsup/cygwin/mount.h3
-rw-r--r--winsup/cygwin/path.cc84
-rw-r--r--winsup/cygwin/path.h1
4 files changed, 76 insertions, 32 deletions
diff --git a/winsup/cygwin/mount.cc b/winsup/cygwin/mount.cc
index 262168076..8954a9908 100644
--- a/winsup/cygwin/mount.cc
+++ b/winsup/cygwin/mount.cc
@@ -590,7 +590,7 @@ mount_item::build_win32 (char *dst, const char *src, unsigned *outflags, unsigne
int
mount_info::conv_to_win32_path (const char *src_path, char *dst, device& dev,
- unsigned *flags)
+ unsigned *flags, bool hide_cygwin_virtuals)
{
bool chroot_ok = !cygheap->root.exists ();
@@ -617,6 +617,13 @@ mount_info::conv_to_win32_path (const char *src_path, char *dst, device& dev,
converting normalizex UNIX path to a DOS-style path, looking up the
appropriate drive in the mount table. */
+ if (hide_cygwin_virtuals)
+ {
+ dev = *fs_dev;
+ backslashify (src_path, dst, 0);
+ rc = 0;
+ goto out_no_chroot_check;
+ }
/* See if this is a cygwin "device" */
if (win32_device_name (src_path, dst, dev))
{
@@ -1428,6 +1435,17 @@ mount_info::add_item (const char *native, const char *posix,
if (posix == NULL || !isabspath (posix) ||
is_unc_share (posix) || isdrive (posix))
posixerr = EINVAL;
+ else if (posix[0] == '/' && posix[1] == 0)
+ {
+ /* Special case hack for root, because the Cygnal
+ * version of normalize_posix_path
+ * doesn't handle this.
+ */
+ posixtail = posixtmp;
+ *posixtail++ = '/';
+ *posixtail = '\0';
+ posixerr = 0;
+ }
else
posixerr = normalize_posix_path (posix, posixtmp, posixtail);
diff --git a/winsup/cygwin/mount.h b/winsup/cygwin/mount.h
index d37b673e6..ee2339581 100644
--- a/winsup/cygwin/mount.h
+++ b/winsup/cygwin/mount.h
@@ -193,7 +193,8 @@ class mount_info
unsigned set_flags_from_win32_path (const char *path);
int conv_to_win32_path (const char *src_path, char *dst, device&,
- unsigned *flags = NULL);
+ unsigned *flags = NULL,
+ bool hide_cygwin_virtuals = false);
int conv_to_posix_path (PWCHAR src_path, char *posix_path, int ccp_flags);
int conv_to_posix_path (const char *src_path, char *posix_path,
int ccp_flags);
diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc
index 7533e007e..05717b839 100644
--- a/winsup/cygwin/path.cc
+++ b/winsup/cygwin/path.cc
@@ -231,9 +231,30 @@ has_dot_last_component (const char *dir, bool test_dot_dot)
return last_comp == dir || last_comp[-1] == '/';
}
+static int
+is_posix_space(const char *path)
+{
+ const int nprefixes = 2;
+ static const char *prefix[] = { "dev:/", "proc:/" };
+ static int length[] = { 5, 6 };
+ int i;
+
+ for (i = 0; i < nprefixes; i++)
+ {
+ int len = length[i];
+ if (strncmp(path, prefix[i], len) == 0)
+ return len - 2;
+ }
+
+ return 0;
+}
+
/* Normalize a POSIX path.
All duplicate /'s, except for 2 leading /'s, are deleted.
- The result is 0 for success, or an errno error value. */
+ The result is:
+ 0 == success;
+ -1 == success: Win32 path;
+ > 0 == errno error value; */
int
normalize_posix_path (const char *src, char *dst, char *&tail)
@@ -243,28 +264,32 @@ normalize_posix_path (const char *src, char *dst, char *&tail)
bool check_parent = false;
syscall_printf ("src %s", src);
- if ((isdrive (src) && isdirsep (src[2])) || *src == '\\')
+ /*
+ * Under Cygnal, only a few special paths beginning with a prefix
+ * are in a "POSIX space" and are transformed into Cygwin paths
+ * according to this pattern:
+ *
+ * dev:/path/to -> /dev/path/to
+ *
+ * Only certain words are recognized.
+ */
+
+ int len = is_posix_space(src);
+
+ if (!len)
goto win32_path;
tail = dst;
- if (!isslash (src[0]))
- {
- if (!cygheap->cwd.get (dst))
- return get_errno ();
- tail = strchr (tail, '\0');
- if (isslash (dst[0]) && isslash (dst[1]))
- ++dst_start;
- if (*src == '.')
- {
- if (tail == dst_start + 1 && *dst_start == '/')
- tail--;
- goto sawdot;
- }
- if (tail > dst && !isslash (tail[-1]))
- *tail++ = '/';
- }
+
+ *tail++ = '/';
+
+ strncpy(tail, src, len);
+
+ src += len + 1; /* src now points at slash after colon */
+ tail += len; /* dst holds "/word" with no colon */
+
/* Two leading /'s? If so, preserve them. */
- else if (isslash (src[1]) && !isslash (src[2]))
+ if (isslash (src[1]) && !isslash (src[2]))
{
*tail++ = *src++;
++dst_start;
@@ -288,7 +313,6 @@ normalize_posix_path (const char *src, char *dst, char *&tail)
if (*src != '.')
break;
- sawdot:
if (src[1] != '.')
{
if (!src[1])
@@ -766,7 +790,8 @@ path_conv::check (const char *src, unsigned opt,
/* Convert to native path spec sans symbolic link info. */
error = mount_table->conv_to_win32_path (path_copy, full_path,
- dev, &sym.pflags);
+ dev, &sym.pflags,
+ is_msdos);
if (error)
return;
@@ -926,8 +951,10 @@ path_conv::check (const char *src, unsigned opt,
it as caseinsensitive,noacl path. This must be set before
calling sym.check, otherwise the path is potentially treated
casesensitive. */
- if (is_msdos)
+ if (is_msdos) {
sym.pflags |= PATH_NOPOSIX | PATH_NOACL;
+ path_flags |= PATH_NOPOSIX | PATH_NOACL;
+ }
is_fs_via_procsys:
@@ -1358,7 +1385,7 @@ normalize_win32_path (const char *src, char *dst, char *&tail)
if (isdrive (src))
/* Always convert drive letter to uppercase for case sensitivity. */
*tail++ = cyg_toupper (*src++);
- else if (*src != '/')
+ else
{
if (beg_src_slash)
tail += cygheap->cwd.get_drive (dst);
@@ -3224,12 +3251,14 @@ chdir (const char *in_dir)
}
const char *posix_cwd = NULL;
- dev_t devn = path.get_device ();
+
if (!path.exists ())
set_errno (ENOENT);
else if (!path.isdir ())
set_errno (ENOTDIR);
- else if (!isvirtual_dev (devn))
+ else if (!path.is_native ())
+ set_errno (EOPNOTSUPP);
+ else
{
/* The sequence chdir("xx"); chdir(".."); must be a noop if xx
is not a symlink. This is exploited by find.exe.
@@ -3240,11 +3269,6 @@ chdir (const char *in_dir)
posix_cwd = path.get_posix ();
res = 0;
}
- else
- {
- posix_cwd = path.get_posix ();
- res = 0;
- }
if (!res)
res = cygheap->cwd.set (&path, posix_cwd);
diff --git a/winsup/cygwin/path.h b/winsup/cygwin/path.h
index 1e2af6550..c6f43c183 100644
--- a/winsup/cygwin/path.h
+++ b/winsup/cygwin/path.h
@@ -161,6 +161,7 @@ class path_conv
bool has_acls () const {return !(path_flags & PATH_NOACL) && fs.has_acls (); }
bool hasgood_inode () const {return !(path_flags & PATH_IHASH); }
bool isgood_inode (ino_t ino) const;
+ bool is_native () const {return !!(path_flags & PATH_NOPOSIX);}
bool support_sparse () const
{
return (path_flags & PATH_SPARSE)