diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2016-07-11 20:14:00 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2021-07-26 21:52:24 -0700 |
commit | ee6eae5d2bde5dc57a8534bc4b3a07ed176480ce (patch) | |
tree | ea781868c0f3c25739beae407b222667cfb4efea | |
parent | 18bf3105812dfe4a3b3982838175ec9a60372198 (diff) | |
download | cygnal-ee6eae5d2bde5dc57a8534bc4b3a07ed176480ce.tar.gz cygnal-ee6eae5d2bde5dc57a8534bc4b3a07ed176480ce.tar.bz2 cygnal-ee6eae5d2bde5dc57a8534bc4b3a07ed176480ce.zip |
Implement drive-relative paths and per-drive working dir.
* 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.cc | 41 |
1 files changed, 40 insertions, 1 deletions
diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc index edc17152b..807a7c6ef 100644 --- a/winsup/cygwin/path.cc +++ b/winsup/cygwin/path.cc @@ -1481,7 +1481,32 @@ 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++); + + 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++); + } + } *tail++ = *src++; dst = tail; /* If backslash is missing in src, add one. */ @@ -4802,6 +4827,20 @@ cwdstuff::override_win32_cwd (bool init, ULONG old_dismount_count) from the parent process. We always have to close it here. */ 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. */ |