diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2016-07-08 23:06:38 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2016-07-08 23:06:38 -0700 |
commit | a73b5a8f6beb37685888977171cea10af94e77c9 (patch) | |
tree | 2536518d59ba59ac26abf7a0640f5c149e108138 /winsup/cygwin/path.cc | |
parent | eec582cdb351530131d2ae30376eca2771f78e49 (diff) | |
download | cygnal-a73b5a8f6beb37685888977171cea10af94e77c9.tar.gz cygnal-a73b5a8f6beb37685888977171cea10af94e77c9.tar.bz2 cygnal-a73b5a8f6beb37685888977171cea10af94e77c9.zip |
First steps toward native path handling.
- /proc and /dev are are still available, accessed as
proc:/ and dev:/
- All other paths are native, and do not "see" virtual Cygwin
items; /cygdrive is just C:\cygdrive (if the current drive
is C).
- chdir() to a virtual directory like dev:/ or proc:/ results
in errno EOPNOTSUPP.
* winsup/cygwin/mount.cc (mount_info::conv_to_win32_path):
Takes new bool argument, hide_cygwin_virtuals. If true all
that the function does is "backslashify" the path.
(mount_info::add_item): Special hack inserted here so that
we can create the virtual root directory which holds dev
and proc and whatnot, and is passed here as "/". We cannot let
this go through normalize_posix_path any more because it
will turn to C:\.
* winsup/cygwin/mount.h (mount_info::conv_to_win32_path):
Declaration updated.
* winsup/cygwin/path.cc (is_posix_space): New static function:
tests for paths in special spaces, currently "dev:/" and
"proc:/". Used by normalize_posix_path.
(normalize_posix_path): Any path that doesn't satisfy the
is_posix_space test is treated as Win32.
Since the bulk of the code is now only used for these
spaces, the relative path handling is not required
and a the corresponding block of code is removed.
Paths satisfying is_posix_space are transformed.
I.e. the underlying path resolution machine in the path_conv
class still recognizes /proc and /dev. It's just that these
will not occur, because normalize_posix_path will convert
them to references with drive names.
(path_conv::check): Pass the is_msdos flag down to
mount_info::conv_to_win32_path as the new argument. Thus
if normalize_posix_path indicates a native path, this function
will hide the virtual spaces. Also, we add PATH_NOPOSIX and
PATH_NOACL to the object's path_flags. This is used in
chdir.
(normalize_win32_path): A small piece of logic works against
our plan here: it checks for the leading forward slash on the
path, and prevents such paths from being converted to Win32
paths with a drive reference. We eliminate this test, and
treat paths unconditionally.
(chdir): Here, if the path is not native, we return
EOPNOTSUPP. Thus it is impossible to chdir into Cygwin
virtual directories like /dev (now referenced as dev:/).
They can be listed but not turned into the current directory.
Eventually we want chdir to actually set the Win32 current
directory of the process; that can't work for virtual
dirs.
* winsup/cygwin/path.h (path_conv::is_native): New inline
accessor which tests for the PATH_NOPOSIX flag.
Diffstat (limited to 'winsup/cygwin/path.cc')
-rw-r--r-- | winsup/cygwin/path.cc | 84 |
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); |