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.cc84
1 files changed, 54 insertions, 30 deletions
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);