summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2016-07-11 20:14:00 -0700
committerKaz Kylheku <kaz@kylheku.com>2016-07-11 20:14:00 -0700
commitf77ebbd3c5b1c90dc80d6be033b623b8eb86442f (patch)
tree1a331d57a0e0df3defbbfdf6bbe5a453230af989
parentd18238a780f8908b30c9d04b1b204db592346d36 (diff)
downloadcygnal-f77ebbd3c5b1c90dc80d6be033b623b8eb86442f.tar.gz
cygnal-f77ebbd3c5b1c90dc80d6be033b623b8eb86442f.tar.bz2
cygnal-f77ebbd3c5b1c90dc80d6be033b623b8eb86442f.zip
Implement drive-relative paths and per-drive working dir.cygnal-release-2.5.1.98cygnal-release-2.4.98
* winsup/cygwin/path.cc (normalize_win32_path): When a drive-relative path is normalized, look up the remembered working directory of that drive in the environment. A drive-relative path is, for example, "C:file.txt". Or just "C:", with no component. If there is no path for the drive in the environment, then the root directory is used, and the "C:" part thus becomes "C:\", causing the path to refer to "C:\file.txt". Otherwise the path is inserted, with a backslash, like "C:\users\bob\file.txt". The Windows convention for storing these per-drive paths in the environment is to use environment variables based on drive letters. For instance the path for the C drive is stored in the environment variable "!C:" (bang, letter, colon). The path includes the C:\ prefix. (cwdstuff::override_win32_cwd): Add the behavior of associating the current working directory with its drive (if it is a current working directory based on a drive). For instance if the overriding cwd is "C:\Users", then the "C:\Users" path is stored into the "!C:" environment variable.
-rw-r--r--winsup/cygwin/path.cc44
1 files changed, 42 insertions, 2 deletions
diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc
index 05717b839..519aef118 100644
--- a/winsup/cygwin/path.cc
+++ b/winsup/cygwin/path.cc
@@ -1383,8 +1383,34 @@ normalize_win32_path (const char *src, char *dst, char *&tail)
if (tail == dst)
{
if (isdrive (src))
- /* Always convert drive letter to uppercase for case sensitivity. */
- *tail++ = cyg_toupper (*src++);
+ {
+ /* Drive followed by separator is an absolute path */
+ if (isdirsep (src[2]))
+ /* Always convert drive letter to uppercase for case sensitivity. */
+ *tail++ = cyg_toupper (*src++);
+ else
+ {
+ /* Drive-relative path: get drive path from environment. */
+ char env[] = { '!', cyg_toupper (*src), ':', 0 };
+ const char *drvpath = getenv(env);
+
+ if (drvpath)
+ {
+ size_t len = strlcpy(tail, drvpath, NT_MAX_PATH);
+
+ if (len >= NT_MAX_PATH - 1)
+ return ENAMETOOLONG;
+
+ tail += len;
+ *tail++ = '\\';
+ src += 2;
+ }
+ else
+ {
+ *tail++ = cyg_toupper (*src++);
+ }
+ }
+ }
else
{
if (beg_src_slash)
@@ -4406,6 +4432,20 @@ cwdstuff::override_win32_cwd (bool init, ULONG old_dismount_count)
if (h && h != dir)
NtClose (h);
}
+
+ /* Simulate the SetCurrentDirectory effect of associating a drive
+ with its own current directory. This behavior dating all the way
+ back to MS-DOS is done in Windows with special environment
+ variables. */
+ if (iswdrive (win32.Buffer)) {
+ tmp_pathbuf tp;
+ char env[] = { '!', (char) win32.Buffer[0], ':', 0 };
+ char *cwdcopy = tp.c_get ();
+
+ sys_wcstombs (cwdcopy, NT_MAX_PATH, win32.Buffer,
+ win32.Length / sizeof (WCHAR));
+ setenv(env, cwdcopy, 1);
+ }
}
/* Initialize cygcwd 'muto' for serializing access to cwd info. */