* path.cc (cnt_bs): New inline function.
(symlink_native): Fix creating relative native symlink.
This commit is contained in:
parent
42c8e85109
commit
2566c2e600
@ -1,3 +1,8 @@
|
||||
2013-06-17 Corinna Vinschen <corinna@vinschen.de>
|
||||
|
||||
* path.cc (cnt_bs): New inline function.
|
||||
(symlink_native): Fix creating relative native symlink.
|
||||
|
||||
2013-06-17 Corinna Vinschen <corinna@vinschen.de>
|
||||
|
||||
* fhandler_clipboard.cc (fhandler_dev_clipboard::read): Fix buffer
|
||||
|
@ -1530,12 +1530,25 @@ symlink_nfs (const char *oldpath, path_conv &win32_newpath)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Count backslashes between s and e. */
|
||||
static inline int
|
||||
cnt_bs (PWCHAR s, PWCHAR e)
|
||||
{
|
||||
int num = 0;
|
||||
|
||||
while (s < e)
|
||||
if (*s++ == L'\\')
|
||||
++num;
|
||||
return num;
|
||||
}
|
||||
|
||||
static int
|
||||
symlink_native (const char *oldpath, path_conv &win32_newpath)
|
||||
{
|
||||
tmp_pathbuf tp;
|
||||
path_conv win32_oldpath;
|
||||
PUNICODE_STRING final_oldpath, final_newpath;
|
||||
UNICODE_STRING final_oldpath_buf;
|
||||
|
||||
if (isabspath (oldpath))
|
||||
{
|
||||
@ -1554,10 +1567,48 @@ symlink_native (const char *oldpath, path_conv &win32_newpath)
|
||||
stpcpy (stpncpy (absoldpath, win32_newpath.normalized_path, len),
|
||||
oldpath);
|
||||
win32_oldpath.check (absoldpath, PC_SYM_NOFOLLOW, stat_suffixes);
|
||||
UNICODE_STRING dirpath;
|
||||
RtlSplitUnicodePath (win32_newpath.get_nt_native_path (), &dirpath, NULL);
|
||||
final_oldpath = win32_oldpath.get_nt_native_path ();
|
||||
final_oldpath->Buffer += dirpath.Length / sizeof (WCHAR);
|
||||
|
||||
/* Try hard to keep Windows symlink path relative. */
|
||||
|
||||
/* 1. Find common path prefix. */
|
||||
PWCHAR c_old = win32_oldpath.get_nt_native_path ()->Buffer;
|
||||
PWCHAR c_new = win32_newpath.get_nt_native_path ()->Buffer;
|
||||
/* Windows compatible == always check case insensitive. */
|
||||
while (towupper (*c_old++) == towupper (*c_new++))
|
||||
;
|
||||
/* The last component could share a common prefix, so make sure we end
|
||||
up on the first char after the last common backslash. */
|
||||
while (c_old[-1] != L'\\')
|
||||
--c_old, --c_new;
|
||||
|
||||
/* 2. Check if prefix is long enough. The prefix must at least points to
|
||||
a complete device: \\?\X:\ or \\?\UNC\server\share\ are the minimum
|
||||
prefix strings. We start counting behind the \\?\ for speed. */
|
||||
int num = cnt_bs (win32_oldpath.get_nt_native_path ()->Buffer + 4, c_old);
|
||||
if (num < 1 /* locale drive. */
|
||||
|| (win32_oldpath.get_nt_native_path ()->Buffer[6] != L':'
|
||||
&& num < 3)) /* UNC path. */
|
||||
{
|
||||
/* 3a. No valid common path prefix: Create absolute symlink. */
|
||||
final_oldpath = win32_oldpath.get_nt_native_path ();
|
||||
final_oldpath->Buffer[1] = L'\\';
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 3b. Common path prefx. Count number of additional directories
|
||||
in symlink's path, and prepend as much ".." path components
|
||||
to the target path. */
|
||||
PWCHAR e_new = win32_newpath.get_nt_native_path ()->Buffer
|
||||
+ win32_newpath.get_nt_native_path ()->Length
|
||||
/ sizeof (WCHAR);
|
||||
num = cnt_bs (c_new, e_new);
|
||||
final_oldpath = &final_oldpath_buf;
|
||||
final_oldpath->Buffer = tp.w_get ();
|
||||
PWCHAR e_old = final_oldpath->Buffer;
|
||||
while (num-- > 0)
|
||||
e_old = wcpcpy (e_old, L"..\\");
|
||||
wcpcpy (e_old, c_old);
|
||||
}
|
||||
}
|
||||
/* If the symlink target doesn't exist, don't create native symlink.
|
||||
Otherwise the directory flag in the symlink is potentially wrong
|
||||
|
@ -11,3 +11,6 @@ Bug fixes:
|
||||
|
||||
- Fix EFAULT when reading large clipboard.
|
||||
Fixes: http://cygwin.com/ml/cygwin/2013-06/msg00311.html
|
||||
|
||||
- Fix creation of relative native symlinks.
|
||||
Fixes: http://cygwin.com/ml/cygwin/2013-06/msg00340.html
|
||||
|
Loading…
x
Reference in New Issue
Block a user