* path.h (get_nt_native_path): Add third parameter to declaration and
declare with regparms. * path.cc (get_nt_native_path): Add third parameter to allow conversion of leading and trailing dots and spaces on filesystems only supporting filenames following DOS rules. (path_conv::get_nt_native_path): Call get_nt_native_path according to fs.has_dos_filenames_only flag. (getfileattr): Accommodate new parameter to get_nt_native_path. (symlink_info::check): Revamp fs_update_called handling to call fs.update only once per call. Call get_nt_native_path according to fs.has_dos_filenames_only flag. Streamline filesystem dependent code not to be called more than once unnecessarily. Drop code tweaking incoming path for broken filesystems only allowing DOS pathnames. Rely on changed get_nt_native_path instead. * mount.cc (fillout_mntent): Accommodate new parameter to get_nt_native_path. * strfuncs.cc (tfx_rev_chars): New conversion table with comment. (sys_cp_wcstombs): Use tfx_rev_chars rather than tfx_chars.
This commit is contained in:
parent
948214b000
commit
8802178fdd
@ -1,3 +1,24 @@
|
|||||||
|
2010-04-23 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
|
* path.h (get_nt_native_path): Add third parameter to declaration and
|
||||||
|
declare with regparms.
|
||||||
|
* path.cc (get_nt_native_path): Add third parameter to allow conversion
|
||||||
|
of leading and trailing dots and spaces on filesystems only supporting
|
||||||
|
filenames following DOS rules.
|
||||||
|
(path_conv::get_nt_native_path): Call get_nt_native_path according to
|
||||||
|
fs.has_dos_filenames_only flag.
|
||||||
|
(getfileattr): Accommodate new parameter to get_nt_native_path.
|
||||||
|
(symlink_info::check): Revamp fs_update_called handling to call
|
||||||
|
fs.update only once per call. Call get_nt_native_path according to
|
||||||
|
fs.has_dos_filenames_only flag. Streamline filesystem dependent code
|
||||||
|
not to be called more than once unnecessarily. Drop code tweaking
|
||||||
|
incoming path for broken filesystems only allowing DOS pathnames.
|
||||||
|
Rely on changed get_nt_native_path instead.
|
||||||
|
* mount.cc (fillout_mntent): Accommodate new parameter to
|
||||||
|
get_nt_native_path.
|
||||||
|
* strfuncs.cc (tfx_rev_chars): New conversion table with comment.
|
||||||
|
(sys_cp_wcstombs): Use tfx_rev_chars rather than tfx_chars.
|
||||||
|
|
||||||
2010-04-22 Corinna Vinschen <corinna@vinschen.de>
|
2010-04-22 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
* path.cc (symlink_info::check): Make sure to restart only once.
|
* path.cc (symlink_info::check): Make sure to restart only once.
|
||||||
|
@ -1470,7 +1470,7 @@ fillout_mntent (const char *native_path, const char *posix_path, unsigned flags)
|
|||||||
tmp_pathbuf tp;
|
tmp_pathbuf tp;
|
||||||
UNICODE_STRING unat;
|
UNICODE_STRING unat;
|
||||||
tp.u_get (&unat);
|
tp.u_get (&unat);
|
||||||
get_nt_native_path (native_path, unat);
|
get_nt_native_path (native_path, unat, false);
|
||||||
if (append_bs)
|
if (append_bs)
|
||||||
RtlAppendUnicodeToString (&unat, L"\\");
|
RtlAppendUnicodeToString (&unat, L"\\");
|
||||||
mntinfo.update (&unat, NULL);
|
mntinfo.update (&unat, NULL);
|
||||||
|
@ -393,7 +393,7 @@ str2uni_cat (UNICODE_STRING &tgt, const char *srcstr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
PUNICODE_STRING
|
PUNICODE_STRING
|
||||||
get_nt_native_path (const char *path, UNICODE_STRING& upath)
|
get_nt_native_path (const char *path, UNICODE_STRING& upath, bool dos)
|
||||||
{
|
{
|
||||||
upath.Length = 0;
|
upath.Length = 0;
|
||||||
if (path[0] == '/') /* special path w/o NT path representation. */
|
if (path[0] == '/') /* special path w/o NT path representation. */
|
||||||
@ -425,6 +425,26 @@ get_nt_native_path (const char *path, UNICODE_STRING& upath)
|
|||||||
RtlAppendUnicodeStringToString (&upath, &ro_u_natp);
|
RtlAppendUnicodeStringToString (&upath, &ro_u_natp);
|
||||||
str2uni_cat (upath, path + 4);
|
str2uni_cat (upath, path + 4);
|
||||||
}
|
}
|
||||||
|
if (dos)
|
||||||
|
{
|
||||||
|
/* Unfortunately we can't just use transform_chars with the tfx_rev_chars
|
||||||
|
table since only leading and trainlig spaces and dots are affected.
|
||||||
|
So we step to every backslash and fix surrounding dots and spaces.
|
||||||
|
That makes these broken filesystems a bit slower, but, hey. */
|
||||||
|
PWCHAR cp = upath.Buffer + 7;
|
||||||
|
PWCHAR cend = upath.Buffer + upath.Length / sizeof (WCHAR);
|
||||||
|
while (++cp < cend)
|
||||||
|
if (*cp == L'\\')
|
||||||
|
{
|
||||||
|
PWCHAR ccp = cp - 1;
|
||||||
|
while (*ccp == L'.' || *ccp == L' ')
|
||||||
|
*ccp-- |= 0xf000;
|
||||||
|
while (cp[1] == L' ')
|
||||||
|
*++cp |= 0xf000;
|
||||||
|
}
|
||||||
|
while (*--cp == L'.' || *cp == L' ')
|
||||||
|
*cp |= 0xf000;
|
||||||
|
}
|
||||||
return &upath;
|
return &upath;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -437,7 +457,7 @@ path_conv::get_nt_native_path ()
|
|||||||
uni_path.MaximumLength = (strlen (path) + 10) * sizeof (WCHAR);
|
uni_path.MaximumLength = (strlen (path) + 10) * sizeof (WCHAR);
|
||||||
wide_path = (PWCHAR) cmalloc_abort (HEAP_STR, uni_path.MaximumLength);
|
wide_path = (PWCHAR) cmalloc_abort (HEAP_STR, uni_path.MaximumLength);
|
||||||
uni_path.Buffer = wide_path;
|
uni_path.Buffer = wide_path;
|
||||||
::get_nt_native_path (path, uni_path);
|
::get_nt_native_path (path, uni_path, fs.has_dos_filenames_only ());
|
||||||
}
|
}
|
||||||
return &uni_path;
|
return &uni_path;
|
||||||
}
|
}
|
||||||
@ -501,7 +521,7 @@ getfileattr (const char *path, bool caseinsensitive) /* path has to be always ab
|
|||||||
InitializeObjectAttributes (&attr, &upath,
|
InitializeObjectAttributes (&attr, &upath,
|
||||||
caseinsensitive ? OBJ_CASE_INSENSITIVE : 0,
|
caseinsensitive ? OBJ_CASE_INSENSITIVE : 0,
|
||||||
NULL, NULL);
|
NULL, NULL);
|
||||||
get_nt_native_path (path, upath);
|
get_nt_native_path (path, upath, false);
|
||||||
|
|
||||||
status = NtQueryAttributesFile (&attr, &fbi);
|
status = NtQueryAttributesFile (&attr, &fbi);
|
||||||
if (NT_SUCCESS (status))
|
if (NT_SUCCESS (status))
|
||||||
@ -2178,9 +2198,10 @@ symlink_info::check (char *path, const suffix_info *suffixes, unsigned opt,
|
|||||||
IO_STATUS_BLOCK io;
|
IO_STATUS_BLOCK io;
|
||||||
FILE_BASIC_INFORMATION fbi;
|
FILE_BASIC_INFORMATION fbi;
|
||||||
suffix_scan suffix;
|
suffix_scan suffix;
|
||||||
|
bool fs_update_called = false;
|
||||||
|
|
||||||
ULONG ci_flag = cygwin_shared->obcaseinsensitive || (pflags & PATH_NOPOSIX)
|
const ULONG ci_flag = cygwin_shared->obcaseinsensitive
|
||||||
? OBJ_CASE_INSENSITIVE : 0;
|
|| (pflags & PATH_NOPOSIX) ? OBJ_CASE_INSENSITIVE : 0;
|
||||||
/* TODO: Temporarily do all char->UNICODE conversion here. This should
|
/* TODO: Temporarily do all char->UNICODE conversion here. This should
|
||||||
already be slightly faster than using Ascii functions. */
|
already be slightly faster than using Ascii functions. */
|
||||||
tmp_pathbuf tp;
|
tmp_pathbuf tp;
|
||||||
@ -2212,10 +2233,9 @@ restart:
|
|||||||
while (suffix.next ())
|
while (suffix.next ())
|
||||||
{
|
{
|
||||||
bool no_ea = false;
|
bool no_ea = false;
|
||||||
bool fs_update_called = false;
|
|
||||||
|
|
||||||
error = 0;
|
error = 0;
|
||||||
get_nt_native_path (suffix.path, upath);
|
get_nt_native_path (suffix.path, upath, fs.has_dos_filenames_only ());
|
||||||
if (h)
|
if (h)
|
||||||
{
|
{
|
||||||
NtClose (h);
|
NtClose (h);
|
||||||
@ -2261,7 +2281,8 @@ restart:
|
|||||||
}
|
}
|
||||||
if (status == STATUS_OBJECT_NAME_NOT_FOUND)
|
if (status == STATUS_OBJECT_NAME_NOT_FOUND)
|
||||||
{
|
{
|
||||||
if (ci_flag == 0 && wincap.has_broken_udf ())
|
if (ci_flag == 0 && wincap.has_broken_udf ()
|
||||||
|
&& (!fs_update_called || fs.is_udf ()))
|
||||||
{
|
{
|
||||||
/* On NT 5.x UDF is broken (at least) in terms of case
|
/* On NT 5.x UDF is broken (at least) in terms of case
|
||||||
sensitivity. When trying to open a file case sensitive,
|
sensitivity. When trying to open a file case sensitive,
|
||||||
@ -2276,10 +2297,9 @@ restart:
|
|||||||
attr.Attributes = 0;
|
attr.Attributes = 0;
|
||||||
if (NT_SUCCESS (status))
|
if (NT_SUCCESS (status))
|
||||||
{
|
{
|
||||||
fs.update (&upath, h);
|
if (!fs_update_called)
|
||||||
if (fs.is_udf ())
|
fs_update_called = fs.update (&upath, h);
|
||||||
fs_update_called = true;
|
if (!fs.is_udf ())
|
||||||
else
|
|
||||||
{
|
{
|
||||||
NtClose (h);
|
NtClose (h);
|
||||||
status = STATUS_OBJECT_NAME_NOT_FOUND;
|
status = STATUS_OBJECT_NAME_NOT_FOUND;
|
||||||
@ -2295,31 +2315,29 @@ restart:
|
|||||||
we encountered a STATUS_OBJECT_NAME_NOT_FOUND *and* we didn't
|
we encountered a STATUS_OBJECT_NAME_NOT_FOUND *and* we didn't
|
||||||
already attach a suffix *and* the above special case for UDF
|
already attach a suffix *and* the above special case for UDF
|
||||||
on XP didn't succeeed. */
|
on XP didn't succeeed. */
|
||||||
if (!restarted && !*ext_here && !fs_update_called)
|
if (!restarted && !*ext_here
|
||||||
|
&& (!fs_update_called || fs.has_dos_filenames_only ()))
|
||||||
{
|
{
|
||||||
/* Check for leading space or trailing dot or space in
|
/* Check for leading space or trailing dot or space in
|
||||||
last component. */
|
last component. */
|
||||||
char *pend = ext_here;
|
char *pend = ext_here;
|
||||||
while (pend[-1] == '.' || pend[-1] == ' ')
|
if (pend[-1] == '.' || pend[-1] == ' ')
|
||||||
--pend;
|
--pend;
|
||||||
char *pbeg = pend;
|
char *pbeg = pend;
|
||||||
while (pbeg[-1] != '\\')
|
while (pbeg[-1] != '\\')
|
||||||
--pbeg;
|
--pbeg;
|
||||||
/* If so, call fs.update to check if the filesystem is one of
|
/* If so, call fs.update to check if the filesystem is one of
|
||||||
the broken ones. */
|
the broken ones. */
|
||||||
if ((*pbeg == ' ' || *pend != '\0')
|
if (*pbeg == ' ' || *pend != '\0')
|
||||||
&& fs.update (&upath, NULL)
|
|
||||||
&& fs.has_dos_filenames_only ())
|
|
||||||
{
|
{
|
||||||
/* If so, strip leading spaces and trailing dots and spaces
|
if (!fs_update_called)
|
||||||
from filename and... */
|
fs_update_called = fs.update (&upath, NULL);
|
||||||
if (pbeg)
|
if (fs.has_dos_filenames_only ())
|
||||||
while (*pbeg == ' ')
|
{
|
||||||
memmove (pbeg, pbeg + 1, --pend - pbeg);
|
/* If so, try again. */
|
||||||
*pend = '\0';
|
restarted = true;
|
||||||
/* ...try again. */
|
goto restart;
|
||||||
restarted = true;
|
}
|
||||||
goto restart;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2327,7 +2345,7 @@ restart:
|
|||||||
if (NT_SUCCESS (status)
|
if (NT_SUCCESS (status)
|
||||||
/* Check file system while we're having the file open anyway.
|
/* Check file system while we're having the file open anyway.
|
||||||
This speeds up path_conv noticably (~10%). */
|
This speeds up path_conv noticably (~10%). */
|
||||||
&& (fs_update_called || fs.update (&upath, h))
|
&& (fs_update_called || (fs_update_called = fs.update (&upath, h)))
|
||||||
&& NT_SUCCESS (status = fs.has_buggy_basic_info ()
|
&& NT_SUCCESS (status = fs.has_buggy_basic_info ()
|
||||||
? NtQueryAttributesFile (&attr, &fbi)
|
? NtQueryAttributesFile (&attr, &fbi)
|
||||||
: NtQueryInformationFile (h, &io, &fbi, sizeof fbi,
|
: NtQueryInformationFile (h, &io, &fbi, sizeof fbi,
|
||||||
@ -2397,7 +2415,7 @@ restart:
|
|||||||
TRUE, &basename, TRUE);
|
TRUE, &basename, TRUE);
|
||||||
/* Take the opportunity to check file system while we're
|
/* Take the opportunity to check file system while we're
|
||||||
having the handle to the parent dir. */
|
having the handle to the parent dir. */
|
||||||
fs.update (&upath, h);
|
fs_update_called = fs.update (&upath, h);
|
||||||
NtClose (dir);
|
NtClose (dir);
|
||||||
if (!NT_SUCCESS (status))
|
if (!NT_SUCCESS (status))
|
||||||
{
|
{
|
||||||
|
@ -302,7 +302,7 @@ int path_prefix_p (const char *path1, const char *path2, int len1,
|
|||||||
bool is_floppy (const char *);
|
bool is_floppy (const char *);
|
||||||
int normalize_win32_path (const char *, char *, char *&);
|
int normalize_win32_path (const char *, char *, char *&);
|
||||||
int normalize_posix_path (const char *, char *, char *&);
|
int normalize_posix_path (const char *, char *, char *&);
|
||||||
PUNICODE_STRING get_nt_native_path (const char *, UNICODE_STRING&);
|
PUNICODE_STRING get_nt_native_path (const char *, UNICODE_STRING&, bool) __attribute__ ((regparm (3)));
|
||||||
|
|
||||||
/* FIXME: Move to own include file eventually */
|
/* FIXME: Move to own include file eventually */
|
||||||
|
|
||||||
|
@ -23,8 +23,7 @@ details. */
|
|||||||
use area in the U+f0XX range. The affected characters are all control
|
use area in the U+f0XX range. The affected characters are all control
|
||||||
chars 1 <= c <= 31, as well as the characters " * : < > ? |. The backslash
|
chars 1 <= c <= 31, as well as the characters " * : < > ? |. The backslash
|
||||||
is affected as well, but we can't transform it as long as we accept Win32
|
is affected as well, but we can't transform it as long as we accept Win32
|
||||||
paths as input.
|
paths as input. */
|
||||||
The reverse functionality is in function sys_cp_wcstombs. */
|
|
||||||
static const WCHAR tfx_chars[] = {
|
static const WCHAR tfx_chars[] = {
|
||||||
0, 0xf000 | 1, 0xf000 | 2, 0xf000 | 3,
|
0, 0xf000 | 1, 0xf000 | 2, 0xf000 | 3,
|
||||||
0xf000 | 4, 0xf000 | 5, 0xf000 | 6, 0xf000 | 7,
|
0xf000 | 4, 0xf000 | 5, 0xf000 | 6, 0xf000 | 7,
|
||||||
@ -60,6 +59,45 @@ static const WCHAR tfx_chars[] = {
|
|||||||
0xf000 | '|', '}', '~', 127
|
0xf000 | '|', '}', '~', 127
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* This is the table for the reverse functionality in sys_cp_wcstombs.
|
||||||
|
It differs deliberately in two code places (space and dot) to allow
|
||||||
|
converting back space and dot on filesystems only supporting DOS
|
||||||
|
filenames. */
|
||||||
|
static const WCHAR tfx_rev_chars[] = {
|
||||||
|
0, 0xf000 | 1, 0xf000 | 2, 0xf000 | 3,
|
||||||
|
0xf000 | 4, 0xf000 | 5, 0xf000 | 6, 0xf000 | 7,
|
||||||
|
0xf000 | 8, 0xf000 | 9, 0xf000 | 10, 0xf000 | 11,
|
||||||
|
0xf000 | 12, 0xf000 | 13, 0xf000 | 14, 0xf000 | 15,
|
||||||
|
0xf000 | 16, 0xf000 | 17, 0xf000 | 18, 0xf000 | 19,
|
||||||
|
0xf000 | 20, 0xf000 | 21, 0xf000 | 22, 0xf000 | 23,
|
||||||
|
0xf000 | 24, 0xf000 | 25, 0xf000 | 26, 0xf000 | 27,
|
||||||
|
0xf000 | 28, 0xf000 | 29, 0xf000 | 30, 0xf000 | 31,
|
||||||
|
0xf000 | ' ', '!', 0xf000 | '"', '#',
|
||||||
|
'$', '%', '&', 39,
|
||||||
|
'(', ')', 0xf000 | '*', '+',
|
||||||
|
',', '-', 0xf000 | '.', '\\',
|
||||||
|
'0', '1', '2', '3',
|
||||||
|
'4', '5', '6', '7',
|
||||||
|
'8', '9', 0xf000 | ':', ';',
|
||||||
|
0xf000 | '<', '=', 0xf000 | '>', 0xf000 | '?',
|
||||||
|
'@', 'A', 'B', 'C',
|
||||||
|
'D', 'E', 'F', 'G',
|
||||||
|
'H', 'I', 'J', 'K',
|
||||||
|
'L', 'M', 'N', 'O',
|
||||||
|
'P', 'Q', 'R', 'S',
|
||||||
|
'T', 'U', 'V', 'W',
|
||||||
|
'X', 'Y', 'Z', '[',
|
||||||
|
'\\', ']', '^', '_',
|
||||||
|
'`', 'a', 'b', 'c',
|
||||||
|
'd', 'e', 'f', 'g',
|
||||||
|
'h', 'i', 'j', 'k',
|
||||||
|
'l', 'm', 'n', 'o',
|
||||||
|
'p', 'q', 'r', 's',
|
||||||
|
't', 'u', 'v', 'w',
|
||||||
|
'x', 'y', 'z', '{',
|
||||||
|
0xf000 | '|', '}', '~', 127
|
||||||
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
transform_chars (PWCHAR path, PWCHAR path_end)
|
transform_chars (PWCHAR path, PWCHAR path_end)
|
||||||
{
|
{
|
||||||
@ -382,7 +420,7 @@ sys_cp_wcstombs (wctomb_p f_wctomb, const char *charset, char *dst, size_t len,
|
|||||||
Reverse functionality for invalid bytes in a multibyte sequence is
|
Reverse functionality for invalid bytes in a multibyte sequence is
|
||||||
in sys_cp_mbstowcs below. */
|
in sys_cp_mbstowcs below. */
|
||||||
if ((pw & 0xff00) == 0xf000
|
if ((pw & 0xff00) == 0xf000
|
||||||
&& (((cwc = (pw & 0xff)) <= 0x7f && tfx_chars[cwc] >= 0xf000)
|
&& (((cwc = (pw & 0xff)) <= 0x7f && tfx_rev_chars[cwc] >= 0xf000)
|
||||||
|| (cwc >= 0x80 && MB_CUR_MAX > 1)))
|
|| (cwc >= 0x80 && MB_CUR_MAX > 1)))
|
||||||
{
|
{
|
||||||
buf[0] = (char) cwc;
|
buf[0] = (char) cwc;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user