4
0
mirror of git://sourceware.org/git/newlib-cygwin.git synced 2025-02-28 20:15:24 +08:00

* path.cc (cnt_bs): New inline function.

(symlink_native): Fix creating relative native symlink.
This commit is contained in:
Corinna Vinschen 2013-06-17 12:37:09 +00:00
parent 42c8e85109
commit 2566c2e600
3 changed files with 63 additions and 4 deletions

View File

@ -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> 2013-06-17 Corinna Vinschen <corinna@vinschen.de>
* fhandler_clipboard.cc (fhandler_dev_clipboard::read): Fix buffer * fhandler_clipboard.cc (fhandler_dev_clipboard::read): Fix buffer

View File

@ -1530,12 +1530,25 @@ symlink_nfs (const char *oldpath, path_conv &win32_newpath)
return 0; 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 static int
symlink_native (const char *oldpath, path_conv &win32_newpath) symlink_native (const char *oldpath, path_conv &win32_newpath)
{ {
tmp_pathbuf tp; tmp_pathbuf tp;
path_conv win32_oldpath; path_conv win32_oldpath;
PUNICODE_STRING final_oldpath, final_newpath; PUNICODE_STRING final_oldpath, final_newpath;
UNICODE_STRING final_oldpath_buf;
if (isabspath (oldpath)) if (isabspath (oldpath))
{ {
@ -1554,10 +1567,48 @@ symlink_native (const char *oldpath, path_conv &win32_newpath)
stpcpy (stpncpy (absoldpath, win32_newpath.normalized_path, len), stpcpy (stpncpy (absoldpath, win32_newpath.normalized_path, len),
oldpath); oldpath);
win32_oldpath.check (absoldpath, PC_SYM_NOFOLLOW, stat_suffixes); win32_oldpath.check (absoldpath, PC_SYM_NOFOLLOW, stat_suffixes);
UNICODE_STRING dirpath;
RtlSplitUnicodePath (win32_newpath.get_nt_native_path (), &dirpath, NULL); /* Try hard to keep Windows symlink path relative. */
final_oldpath = win32_oldpath.get_nt_native_path ();
final_oldpath->Buffer += dirpath.Length / sizeof (WCHAR); /* 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. /* If the symlink target doesn't exist, don't create native symlink.
Otherwise the directory flag in the symlink is potentially wrong Otherwise the directory flag in the symlink is potentially wrong

View File

@ -11,3 +11,6 @@ Bug fixes:
- Fix EFAULT when reading large clipboard. - Fix EFAULT when reading large clipboard.
Fixes: http://cygwin.com/ml/cygwin/2013-06/msg00311.html 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