Add case-sensitivity.

Unconditionally handle mount points case-sensitive.
	Unconditionally handle virtual paths case-sensitive.
	Unconditionally handle registry paths case-insensitive.
	Otherwise, accommodate case-sensitivity of given path throughout.
	* cygheap.cc (cygheap_root::set): Get additional caseinsensitive
	parameter and store it.
	* cygheap.h (struct cygheap_root_mount_info): Add member
	caseinsensitive.
	* dlfcn.cc (get_full_path_of_dll): Drop PC_NOFULL parameter from call
	to path_conv::check.
	* environ.cc (pcheck_case): Remove.
	(check_case_init): Remove.
	(known): Drop "check_case" option.
	* exceptions.cc (open_stackdumpfile): Add comment.
	* fhandler.cc (fhandler_base::get_default_fmode): Call pathmatch
	instead of strcasematch.
	* fhandler_disk_file.cc: Accommodate case-sensitivity of given path
	throughout.
	(__DIR_mounts::check_mount): Unconditionally check virtual paths
	case-sensitive.
	(fhandler_disk_file::link): Drop case clash handling.
	(fhandler_disk_file::open): Ditto.
	(fhandler_disk_file::readdir_helper): Drop managed mount code.
	* mount.cc: Remove managed mount code and datastructures.
	(struct opt): Remove "managed" option.  Add "posix=0" and "posix=1"
	options.
	(fillout_mntent): Remove "managed" output.  Add "posix" output.
	* path.cc (struct symlink_info): Remove case_clash member and
	case_check method.
	(pcheck_case): Remove.
	(path_prefix_p): Take additional bool parameter "caseinsensitive".
	(pathnmatch): Ditto.
	(pathmatch): Ditto.
	(mkrelpath): Ditto.
	(fs_info::update): Set caseinsensitive flag according to file system
	name and FILE_CASE_SENSITIVE_SEARCH flag.  Add comment.
	(tfx_chars_managed): Remove.
	(transform_chars): Drop "managed" parameter.  Always use tfx_chars.
	(get_nt_native_path): Drop "managed" parameter.  Make sure drive letters
	are always upper case.
	(getfileattr): Change second parameter to denote caseinsensitivity.
	(path_conv::check): Initialize caseinsensitive to OBJ_CASE_INSENSITIVE.
	Set caseinsensitive according to global obcaseinsensitive flag, file
	system case sensitivity and MOUNT_NOPOSIX mount flag.
	Drop case_clash and all the related code.
	(symlink_worker): Drop case clash handling.
	(symlink_info::set): Drop setting case_clash.
	(symlink_info::case_check): Remove.
	(cwdstuff::set): Add comment.
	(etc::init): Take path_conv instead of PUNICODE_STRING as parameter to
	allow case sensitivity.
	* path.h (enum pathconv_arg): Drop PC_SYM_IGNORE.
	(enum case_checking): Remove.
	(enum path_types): Drop PATH_ENC, add PATH_NOPOSIX flag.
	(struct fs_info): Add caseinsensitive flag and accessor methods.
	(class path_conv): Add caseinsensitive member and define
	objcaseinsensitive method.  Drop case_clash member and isencoded method.
	(pathmatch): Change prototype according to above change.
	(pathnmatch): Ditto.
	(path_prefix_p): Ditto.
	(get_nt_native_path): Ditto.
	(class etc): Ditto.
	(fnunmunge): Remove prototype.
	* shared.cc (shared_info::init_obcaseinsensitive): Initialize
	obcaseinsensitive flag from obcaseinsensitive registry value.
	(shared_info::initialize): Call init_obcaseinsensitive here by the
	first process creating the shared memory.
	* shared_info.h (mount_item::fnmunge): Remove.
	(shared_info::obcaseinsensitive): Rename from obcaseinsensitivity.
	(shared_info::init_obcaseinsensitive): Declare.
	* syscalls.cc (try_to_bin): Add comment.
	* include/sys/mount.h (MOUNT_ENC): Remove flag.
	(MOUNT_NOPOSIX): Add flag.
This commit is contained in:
Corinna Vinschen 2008-07-16 20:20:45 +00:00
parent bed5a336c4
commit e4b575030b
22 changed files with 288 additions and 490 deletions

View File

@ -1,3 +1,80 @@
2008-07-16 Corinna Vinschen <corinna@vinschen.de>
Add case-sensitivity.
Unconditionally handle mount points case-sensitive.
Unconditionally handle virtual paths case-sensitive.
Unconditionally handle registry paths case-insensitive.
Otherwise, accommodate case-sensitivity of given path throughout.
* cygheap.cc (cygheap_root::set): Get additional caseinsensitive
parameter and store it.
* cygheap.h (struct cygheap_root_mount_info): Add member
caseinsensitive.
* dlfcn.cc (get_full_path_of_dll): Drop PC_NOFULL parameter from call
to path_conv::check.
* environ.cc (pcheck_case): Remove.
(check_case_init): Remove.
(known): Drop "check_case" option.
* exceptions.cc (open_stackdumpfile): Add comment.
* fhandler.cc (fhandler_base::get_default_fmode): Call pathmatch
instead of strcasematch.
* fhandler_disk_file.cc: Accommodate case-sensitivity of given path
throughout.
(__DIR_mounts::check_mount): Unconditionally check virtual paths
case-sensitive.
(fhandler_disk_file::link): Drop case clash handling.
(fhandler_disk_file::open): Ditto.
(fhandler_disk_file::readdir_helper): Drop managed mount code.
* mount.cc: Remove managed mount code and datastructures.
(struct opt): Remove "managed" option. Add "posix=0" and "posix=1"
options.
(fillout_mntent): Remove "managed" output. Add "posix" output.
* path.cc (struct symlink_info): Remove case_clash member and
case_check method.
(pcheck_case): Remove.
(path_prefix_p): Take additional bool parameter "caseinsensitive".
(pathnmatch): Ditto.
(pathmatch): Ditto.
(mkrelpath): Ditto.
(fs_info::update): Set caseinsensitive flag according to file system
name and FILE_CASE_SENSITIVE_SEARCH flag. Add comment.
(tfx_chars_managed): Remove.
(transform_chars): Drop "managed" parameter. Always use tfx_chars.
(get_nt_native_path): Drop "managed" parameter. Make sure drive letters
are always upper case.
(getfileattr): Change second parameter to denote caseinsensitivity.
(path_conv::check): Initialize caseinsensitive to OBJ_CASE_INSENSITIVE.
Set caseinsensitive according to global obcaseinsensitive flag, file
system case sensitivity and MOUNT_NOPOSIX mount flag.
Drop case_clash and all the related code.
(symlink_worker): Drop case clash handling.
(symlink_info::set): Drop setting case_clash.
(symlink_info::case_check): Remove.
(cwdstuff::set): Add comment.
(etc::init): Take path_conv instead of PUNICODE_STRING as parameter to
allow case sensitivity.
* path.h (enum pathconv_arg): Drop PC_SYM_IGNORE.
(enum case_checking): Remove.
(enum path_types): Drop PATH_ENC, add PATH_NOPOSIX flag.
(struct fs_info): Add caseinsensitive flag and accessor methods.
(class path_conv): Add caseinsensitive member and define
objcaseinsensitive method. Drop case_clash member and isencoded method.
(pathmatch): Change prototype according to above change.
(pathnmatch): Ditto.
(path_prefix_p): Ditto.
(get_nt_native_path): Ditto.
(class etc): Ditto.
(fnunmunge): Remove prototype.
* shared.cc (shared_info::init_obcaseinsensitive): Initialize
obcaseinsensitive flag from obcaseinsensitive registry value.
(shared_info::initialize): Call init_obcaseinsensitive here by the
first process creating the shared memory.
* shared_info.h (mount_item::fnmunge): Remove.
(shared_info::obcaseinsensitive): Rename from obcaseinsensitivity.
(shared_info::init_obcaseinsensitive): Declare.
* syscalls.cc (try_to_bin): Add comment.
* include/sys/mount.h (MOUNT_ENC): Remove flag.
(MOUNT_NOPOSIX): Add flag.
2008-07-15 Corinna Vinschen <corinna@vinschen.de>
* fhandler_tape.cc (mtinfo::initialize): Remove synchronization stuff.

View File

@ -396,7 +396,7 @@ cstrdup1 (const char *s)
}
void
cygheap_root::set (const char *posix, const char *native)
cygheap_root::set (const char *posix, const char *native, bool caseinsensitive)
{
if (*posix == '/' && posix[1] == '\0')
{
@ -418,6 +418,7 @@ cygheap_root::set (const char *posix, const char *native)
m->native_pathlen = strlen (native);
if (m->native_pathlen >= 1 && m->native_path[m->native_pathlen - 1] == '\\')
m->native_path[--m->native_pathlen] = '\0';
m->caseinsensitive = caseinsensitive;
}
cygheap_user::~cygheap_user ()

View File

@ -53,6 +53,7 @@ struct cygheap_root_mount_info
unsigned posix_pathlen;
char native_path[CYG_MAX_PATH];
unsigned native_pathlen;
bool caseinsensitive;
};
/* CGF: FIXME This doesn't belong here */
@ -68,7 +69,8 @@ public:
{
if (!m)
return 1;
return path_prefix_p (m->posix_path, path, m->posix_pathlen);
return path_prefix_p (m->posix_path, path, m->posix_pathlen,
m->caseinsensitive);
}
bool ischroot_native (const char *path)
{
@ -87,7 +89,7 @@ public:
return p;
}
bool exists () {return !!m;}
void set (const char *, const char *);
void set (const char *, const char *, bool);
size_t posix_length () const { return m->posix_pathlen; }
const char *posix_path () const { return m->posix_path; }
size_t native_length () const { return m->native_pathlen; }

View File

@ -63,7 +63,7 @@ get_full_path_of_dll (const char* str, char *name)
if (isabspath (name) ||
(ret = check_path_access ("LD_LIBRARY_PATH=", name, real_filename)
?: check_path_access ("/usr/lib", name, real_filename)) == NULL)
real_filename.check (name, PC_SYM_FOLLOW | PC_NOFULL | PC_NULLEMPTY); /* Convert */
real_filename.check (name, PC_SYM_FOLLOW | PC_NULLEMPTY); /* Convert */
if (!real_filename.error)
ret = strcpy (name, real_filename.get_win32 ());

View File

@ -34,7 +34,6 @@ extern bool allow_glob;
extern bool ignore_case_with_glob;
extern bool allow_winsymlinks;
extern bool strip_title_path;
extern int pcheck_case;
bool reset_com = false;
static bool envcache = true;
#ifdef USE_SERVER
@ -490,33 +489,6 @@ glob_init (const char *buf)
}
}
static void
check_case_init (const char *buf)
{
if (!buf || !*buf)
return;
if (ascii_strncasematch (buf, "relax", 5))
{
pcheck_case = PCHECK_RELAXED;
debug_printf ("File case checking set to RELAXED");
}
else if (ascii_strcasematch (buf, "adjust"))
{
pcheck_case = PCHECK_ADJUST;
debug_printf ("File case checking set to ADJUST");
}
else if (ascii_strcasematch (buf, "strict"))
{
pcheck_case = PCHECK_STRICT;
debug_printf ("File case checking set to STRICT");
}
else
{
debug_printf ("Wrong case checking name: %s", buf);
}
}
void
set_file_api_mode (codepage_type cp)
{
@ -595,7 +567,6 @@ static struct parse_thing
} known[] NO_COPY =
{
{"binmode", {x: &binmode}, justset, NULL, {{O_TEXT}, {O_BINARY}}},
{"check_case", {func: &check_case_init}, isfunc, NULL, {{0}, {0}}},
{"codepage", {func: &codepage_init}, isfunc, NULL, {{0}, {0}}},
{"dosfilewarning", {&dos_file_warning}, justset, NULL, {{false}, {true}}},
{"envcache", {&envcache}, justset, NULL, {{true}, {false}}},

View File

@ -149,7 +149,7 @@ open_stackdumpfile ()
p, strlen (p)) * sizeof (WCHAR);
RtlAppendUnicodeToString (&ucore, L".stackdump");
/* Create an object attribute which refers to <progname>.stackdump
in Cygwin's cwd. */
in Cygwin's cwd. Stick to caseinsensitivity. */
InitializeObjectAttributes (&attr, &ucore, OBJ_CASE_INSENSITIVE,
cygheap->cwd.get_handle (), NULL);
HANDLE h;

View File

@ -325,7 +325,7 @@ fhandler_base::get_default_fmode (int flags)
if (pflen > nlen || (stem != get_name () && !isdirsep (stem[-1])))
continue;
else if ((pf->flags & O_ACCMODE) == accflags
&& strcasematch (stem, pf->name))
&& pathmatch (stem, pf->name, !!pc.objcaseinsensitive ()))
{
fmode = pf->flags & ~O_ACCMODE;
break;

View File

@ -81,20 +81,20 @@ public:
UNICODE_STRING proc;
RtlInitUnicodeString (&proc, L"proc");
if (RtlEqualUnicodeString (fname, &proc, TRUE))
if (RtlEqualUnicodeString (fname, &proc, FALSE))
{
found[__DIR_PROC] = true;
return 2;
}
if (fname->Length / sizeof (WCHAR) == mount_table->cygdrive_len - 2
&& RtlEqualUnicodeString (fname, &cygdrive, TRUE))
&& RtlEqualUnicodeString (fname, &cygdrive, FALSE))
{
found[__DIR_CYGDRIVE] = true;
return 2;
}
}
for (int i = 0; i < count; ++i)
if (RtlEqualUnicodeString (fname, &mounts[i], TRUE))
if (RtlEqualUnicodeString (fname, &mounts[i], FALSE))
{
found[i] = true;
return eval ? eval_ino (i) : 1;
@ -233,7 +233,7 @@ path_conv::ndisk_links (DWORD nNumberOfLinks)
RtlInitCountedUnicodeString (&fname, pfdi->FileName,
pfdi->FileNameLength);
InitializeObjectAttributes (&attr, &fname,
OBJ_CASE_INSENSITIVE, fh, NULL);
objcaseinsensitive (), fh, NULL);
if (is_volume_mountpoint (&attr))
++count;
}
@ -379,7 +379,7 @@ fhandler_base::fstat_by_name (struct __stat64 *buf)
LARGE_INTEGER FileId;
RtlSplitUnicodePath (pc.get_nt_native_path (), &dirname, &basename);
InitializeObjectAttributes (&attr, &dirname, OBJ_CASE_INSENSITIVE,
InitializeObjectAttributes (&attr, &dirname, pc.objcaseinsensitive (),
NULL, NULL);
if (!NT_SUCCESS (status = NtOpenFile (&dir, SYNCHRONIZE | FILE_LIST_DIRECTORY,
&attr, &io, FILE_SHARE_VALID_FLAGS,
@ -1123,7 +1123,7 @@ fhandler_disk_file::link (const char *newpath)
path_conv newpc (newpath, PC_SYM_NOFOLLOW | PC_POSIX, stat_suffixes);
if (newpc.error)
{
set_errno (newpc.case_clash ? ECASECLASH : newpc.error);
set_errno (newpc.error);
return -1;
}
@ -1135,7 +1135,7 @@ fhandler_disk_file::link (const char *newpath)
}
char new_buf[strlen (newpath) + 5];
if (!newpc.error && !newpc.case_clash)
if (!newpc.error)
{
if (allow_winsymlinks && pc.is_lnk_special ())
{
@ -1298,13 +1298,6 @@ fhandler_disk_file::open (int flags, mode_t mode)
int
fhandler_base::open_fs (int flags, mode_t mode)
{
if (pc.case_clash && flags & O_CREAT)
{
debug_printf ("case clash detected");
set_errno (ECASECLASH);
return 0;
}
/* Unfortunately NT allows to open directories for writing, but that's
disallowed according to SUSv3. */
if (pc.isdir () && (flags & O_ACCMODE) != O_RDONLY)
@ -1683,7 +1676,7 @@ fhandler_disk_file::readdir_helper (DIR *dir, dirent *de, DWORD w32_err,
OBJECT_ATTRIBUTES attr;
IO_STATUS_BLOCK io;
InitializeObjectAttributes (&attr, fname, OBJ_CASE_INSENSITIVE,
InitializeObjectAttributes (&attr, fname, pc.objcaseinsensitive (),
get_handle (), NULL);
if (is_volume_mountpoint (&attr)
&& (NT_SUCCESS (NtOpenFile (&reph, READ_CONTROL, &attr, &io,
@ -1729,18 +1722,8 @@ fhandler_disk_file::readdir_helper (DIR *dir, dirent *de, DWORD w32_err,
}
}
#if 0
if (pc.isencoded ())
{
char tmp[NAME_MAX + 1];
sys_wcstombs (tmp, NAME_MAX + 1, fname->Buffer,
fname->Length / sizeof (WCHAR));
fnunmunge (de->d_name, tmp);
}
else
#endif
sys_wcstombs (de->d_name, NAME_MAX + 1, fname->Buffer,
fname->Length / sizeof (WCHAR));
sys_wcstombs (de->d_name, NAME_MAX + 1, fname->Buffer,
fname->Length / sizeof (WCHAR));
if (dir->__d_position == 0 && !strcmp (de->d_name, "."))
dir->__flags |= dirent_saw_dot;
@ -1886,7 +1869,8 @@ go_ahead:
{
HANDLE hdl;
InitializeObjectAttributes (&attr, &fname, OBJ_CASE_INSENSITIVE,
InitializeObjectAttributes (&attr, &fname,
pc.objcaseinsensitive (),
get_handle (), NULL);
if (NT_SUCCESS (NtOpenFile (&hdl, READ_CONTROL, &attr, &io,
FILE_SHARE_VALID_FLAGS,
@ -1964,7 +1948,7 @@ fhandler_disk_file::rewinddir (DIR *dir)
HANDLE new_dir;
RtlInitUnicodeString (&fname, L"");
InitializeObjectAttributes (&attr, &fname, OBJ_CASE_INSENSITIVE,
InitializeObjectAttributes (&attr, &fname, pc.objcaseinsensitive (),
get_handle (), NULL);
status = NtOpenFile (&new_dir, SYNCHRONIZE | FILE_LIST_DIRECTORY,
&attr, &io, FILE_SHARE_VALID_FLAGS,

View File

@ -117,7 +117,8 @@ fhandler_proc::get_proc_fhandler (const char *path)
for (int i = 0; proc_listing[i]; i++)
{
if (path_prefix_p (proc_listing[i], path, strlen (proc_listing[i])))
if (path_prefix_p (proc_listing[i], path, strlen (proc_listing[i]),
false))
return proc_fhandlers[i];
}
@ -152,7 +153,7 @@ fhandler_proc::exists ()
if (*path == 0)
return 2;
for (int i = 0; proc_listing[i]; i++)
if (pathmatch (path + 1, proc_listing[i]))
if (!strcmp (path + 1, proc_listing[i]))
{
fileid = i;
return (proc_fhandlers[i] == FH_PROC) ? (i == PROC_SELF ? -2 : -1) : 1;
@ -188,7 +189,7 @@ fhandler_proc::fstat (struct __stat64 *buf)
{
path++;
for (int i = 0; proc_listing[i]; i++)
if (pathmatch (path, proc_listing[i]))
if (!strcmp (path, proc_listing[i]))
{
if (proc_fhandlers[i] != FH_PROC)
buf->st_mode |= S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH;
@ -273,7 +274,8 @@ fhandler_proc::open (int flags, mode_t mode)
proc_file_no = -1;
for (int i = 0; proc_listing[i]; i++)
if (path_prefix_p (proc_listing[i], path + 1, strlen (proc_listing[i])))
if (path_prefix_p (proc_listing[i], path + 1, strlen (proc_listing[i]),
false))
{
proc_file_no = i;
if (proc_fhandlers[i] != FH_PROC)

View File

@ -107,12 +107,12 @@ fhandler_process::exists ()
return 2;
for (int i = 0; process_listing[i]; i++)
if (pathmatch (path + 1, process_listing[i]))
if (!strcmp (path + 1, process_listing[i]))
{
fileid = i;
return is_symlink (i) ? -2 : (i == PROCESS_FD) ? 1 : -1;
}
if (pathnmatch (strchr (path, '/') + 1, "fd/", 3))
if (!strncmp (strchr (path, '/') + 1, "fd/", 3))
{
fileid = PROCESS_FD;
if (fill_filebuf ())
@ -270,8 +270,8 @@ fhandler_process::open (int flags, mode_t mode)
process_file_no = -1;
for (int i = 0; process_listing[i]; i++)
{
if (path_prefix_p
(process_listing[i], path + 1, strlen (process_listing[i])))
if (path_prefix_p (process_listing[i], path + 1,
strlen (process_listing[i]), false))
process_file_no = i;
}
if (process_file_no == -1)

View File

@ -65,7 +65,7 @@ fhandler_procnet::exists ()
return 1;
for (int i = 0; process_listing[i]; i++)
if (pathmatch (path + 1, process_listing[i]))
if (!strcmp (path + 1, process_listing[i]))
{
if (i == PROCNET_IFINET6)
{
@ -167,8 +167,8 @@ fhandler_procnet::open (int flags, mode_t mode)
process_file_no = -1;
for (int i = 0; process_listing[i]; i++)
{
if (path_prefix_p
(process_listing[i], path + 1, strlen (process_listing[i])))
if (path_prefix_p (process_listing[i], path + 1,
strlen (process_listing[i]), false))
process_file_no = i;
}
if (process_file_no == -1)

View File

@ -117,8 +117,8 @@ fhandler_registry::exists ()
if (file == path)
{
for (int i = 0; registry_listing[i]; i++)
if (path_prefix_p
(registry_listing[i], path, strlen (registry_listing[i])))
if (path_prefix_p (registry_listing[i], path,
strlen (registry_listing[i]), true))
{
file_type = 1;
goto out;
@ -140,7 +140,7 @@ fhandler_registry::exists ()
NULL, NULL))
|| (error == ERROR_MORE_DATA))
{
if (pathmatch (buf, file))
if (strcasematch (buf, file))
{
file_type = 1;
goto out;
@ -159,8 +159,8 @@ fhandler_registry::exists ()
NULL, NULL))
|| (error == ERROR_MORE_DATA))
{
if (pathmatch (buf, file) || (buf[0] == '\0' &&
pathmatch (file, DEFAULT_VALUE_NAME)))
if (strcasematch (buf, file)
|| (buf[0] == '\0' && strcasematch (file, DEFAULT_VALUE_NAME)))
{
file_type = -1;
goto out;
@ -461,8 +461,8 @@ fhandler_registry::open (int flags, mode_t mode)
if (file == path)
{
for (int i = 0; registry_listing[i]; i++)
if (path_prefix_p
(registry_listing[i], path, strlen (registry_listing[i])))
if (path_prefix_p (registry_listing[i], path,
strlen (registry_listing[i]), true))
{
if ((flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
{
@ -520,7 +520,7 @@ fhandler_registry::open (int flags, mode_t mode)
set_io_handle (handle);
if (pathmatch (file, DEFAULT_VALUE_NAME))
if (strcasematch (file, DEFAULT_VALUE_NAME))
value_name = cstrdup ("");
else
value_name = cstrdup (file);
@ -631,7 +631,7 @@ value_not_found:
(error = RegEnumKeyEx (handle, index++, buf, &buf_size, NULL, NULL,
NULL, NULL)) || (error == ERROR_MORE_DATA))
{
if (pathmatch (buf, value_name))
if (strcasematch (buf, value_name))
{
set_errno (EISDIR);
return false;
@ -694,7 +694,7 @@ open_key (const char *name, REGSAM access, DWORD wow64, bool isValue)
else
{
for (int i = 0; registry_listing[i]; i++)
if (pathmatch (component, registry_listing[i]))
if (strcasematch (component, registry_listing[i]))
hKey = registry_keys[i];
if (hKey == (HKEY) INVALID_HANDLE_VALUE)
return hKey;

View File

@ -29,9 +29,9 @@ enum
MOUNT_NOTEXEC = 0x0100, /* don't check files for executable magic */
MOUNT_DEVFS = 0x0200, /* /device "filesystem" */
MOUNT_PROC = 0x0400, /* /proc "filesystem" */
MOUNT_ENC = 0x0800, /* encode special characters */
MOUNT_RO = 0x1000, /* read-only "filesystem" */
MOUNT_NOACL = 0x2000 /* support reading/writing ACLs */
MOUNT_NOACL = 0x2000, /* support reading/writing ACLs */
MOUNT_NOPOSIX = 0x4000 /* Case insensitve path handling */
};
int mount (const char *, const char *, unsigned __flags);

View File

@ -841,7 +841,7 @@ mmap64 (void *addr, size_t len, int prot, int flags, int fd, _off64_t off)
IO_STATUS_BLOCK io;
RtlInitUnicodeString (&fname, L"");
InitializeObjectAttributes (&attr, &fname, OBJ_CASE_INSENSITIVE,
InitializeObjectAttributes (&attr, &fname, fh->pc.objcaseinsensitive (),
fh->get_handle (), NULL);
status = NtOpenFile (&h,
fh->get_access () | GENERIC_EXECUTE | SYNCHRONIZE,

View File

@ -32,7 +32,7 @@ details. */
/* Determine if path prefix matches current cygdrive */
#define iscygdrive(path) \
(path_prefix_p (mount_table->cygdrive, (path), mount_table->cygdrive_len))
(path_prefix_p (mount_table->cygdrive, (path), mount_table->cygdrive_len, false))
#define iscygdrive_device(path) \
(isalpha (path[mount_table->cygdrive_len]) && \
@ -40,7 +40,7 @@ details. */
!path[mount_table->cygdrive_len + 1]))
#define isproc(path) \
(path_prefix_p (proc, (path), proc_len))
(path_prefix_p (proc, (path), proc_len, false))
/* is_unc_share: Return non-zero if PATH begins with //server/share
or with one of the native prefixes //./ or //?/
@ -150,161 +150,6 @@ set_flags (unsigned *flags, unsigned val)
}
}
static char dot_special_chars[] =
"."
"\001" "\002" "\003" "\004" "\005" "\006" "\007" "\010"
"\011" "\012" "\013" "\014" "\015" "\016" "\017" "\020"
"\021" "\022" "\023" "\024" "\025" "\026" "\027" "\030"
"\031" "\032" "\033" "\034" "\035" "\036" "\037" ":"
"\\" "*" "?" "%" "\"" "<" ">" "|"
"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";
static char *special_chars = dot_special_chars + 1;
static char special_introducers[] =
"anpcl";
static char
special_char (const char *s, const char *valid_chars = special_chars)
{
if (*s != '%' || strlen (s) < 3)
return 0;
char *p;
char hex[] = {s[1], s[2], '\0'};
unsigned char c = strtoul (hex, &p, 16);
p = strechr (valid_chars, c);
return *p;
}
/* Determines if name is "special". Assumes that name is empty or "absolute" */
static int
special_name (const char *s, int inc = 1)
{
if (!*s)
return false;
s += inc;
if (strcmp (s, ".") == 0 || strcmp (s, "..") == 0)
return false;
int n;
const char *p = NULL;
if (ascii_strncasematch (s, "conin$", n = 5)
|| ascii_strncasematch (s, "conout$", n = 7)
|| ascii_strncasematch (s, "nul", n = 3)
|| ascii_strncasematch (s, "aux", 3)
|| ascii_strncasematch (s, "prn", 3)
|| ascii_strncasematch (s, "con", 3))
p = s + n;
else if (ascii_strncasematch (s, "com", 3)
|| ascii_strncasematch (s, "lpt", 3))
strtoul (s + 3, (char **) &p, 10);
if (p && (*p == '\0' || *p == '.'))
return -1;
return (strchr (s, '\0')[-1] == '.')
|| (strpbrk (s, special_chars) && !ascii_strncasematch (s, "%2f", 3));
}
bool
fnunmunge (char *dst, const char *src)
{
bool converted = false;
char c;
if ((c = special_char (src, special_introducers)))
{
__small_sprintf (dst, "%c%s", c, src + 3);
if (special_name (dst, 0))
{
*dst++ = c;
src += 3;
}
}
while (*src)
if (!(c = special_char (src, dot_special_chars)))
*dst++ = *src++;
else
{
converted = true;
*dst++ = c;
src += 3;
}
*dst = *src;
return converted;
}
static bool
copy1 (char *&d, const char *&src, int& left)
{
left--;
if (left || !*src)
*d++ = *src++;
else
return true;
return false;
}
static bool
copyenc (char *&d, const char *&src, int& left)
{
char buf[16];
int n = __small_sprintf (buf, "%%%02x", (unsigned char) *src++);
left -= n;
if (left <= 0)
return true;
strcpy (d, buf);
d += n;
return false;
}
int
mount_item::fnmunge (char *dst, const char *src, int& left)
{
int name_type;
if (!(name_type = special_name (src)))
{
if ((int) strlen (src) >= left)
return ENAMETOOLONG;
else
strcpy (dst, src);
}
else
{
char *d = dst;
if (copy1 (d, src, left))
return ENAMETOOLONG;
if (name_type < 0 && copyenc (d, src, left))
return ENAMETOOLONG;
while (*src)
if (!strchr (special_chars, *src) || (*src == '%' && !special_char (src)))
{
if (copy1 (d, src, left))
return ENAMETOOLONG;
}
else if (copyenc (d, src, left))
return ENAMETOOLONG;
char dot[] = ".";
const char *p = dot;
if (*--d != '.')
d++;
else if (copyenc (d, p, left))
return ENAMETOOLONG;
*d = *src;
}
backslashify (dst, dst, 0);
return 0;
}
int
mount_item::build_win32 (char *dst, const char *src, unsigned *outflags, unsigned chroot_pathlen)
{
@ -328,37 +173,12 @@ mount_item::build_win32 (char *dst, const char *src, unsigned *outflags, unsigne
const char *p = src + real_posix_pathlen;
if (*p == '/')
/* nothing */;
else if ((!(flags & MOUNT_ENC) && isdrive (dst) && !dst[2]) || *p)
else if ((isdrive (dst) && !dst[2]) || *p)
dst[n++] = '\\';
//if (!*p || !(flags & MOUNT_ENC))
//{
if ((n + strlen (p)) >= NT_MAX_PATH)
err = ENAMETOOLONG;
else
backslashify (p, dst + n, 0);
#if 0
}
if ((n + strlen (p)) >= NT_MAX_PATH)
err = ENAMETOOLONG;
else
{
int left = NT_MAX_PATH - n;
while (*p)
{
char slash = 0;
char *s = strchr (p + 1, '/');
if (s)
{
slash = *s;
*s = '\0';
}
err = fnmunge (dst += n, p, left);
if (!s || err)
break;
n = strlen (dst);
*s = slash;
p = s;
}
}
#endif
backslashify (p, dst + n, 0);
return err;
}
@ -493,7 +313,7 @@ mount_info::conv_to_win32_path (const char *src_path, char *dst, device& dev,
continue;
}
if (path_prefix_p (path, src_path, len))
if (path_prefix_p (path, src_path, len, mi->flags & MOUNT_NOPOSIX))
break;
}
@ -693,7 +513,8 @@ mount_info::conv_to_posix_path (const char *src_path, char *posix_path,
for (int i = 0; i < nmounts; ++i)
{
mount_item &mi = mount[native_sorted[i]];
if (!path_prefix_p (mi.native_path, pathbuf, mi.native_pathlen))
if (!path_prefix_p (mi.native_path, pathbuf, mi.native_pathlen,
mi.flags & MOUNT_NOPOSIX))
continue;
if (cygheap->root.exists () && !cygheap->root.posix_ok (mi.posix_path))
@ -726,14 +547,6 @@ mount_info::conv_to_posix_path (const char *src_path, char *posix_path,
const char *p = cygheap->root.unchroot (posix_path);
memmove (posix_path, p, strlen (p) + 1);
}
#if 0
if (mi.flags & MOUNT_ENC)
{
char *tmpbuf = tp.c_get ();
if (fnunmunge (tmpbuf, posix_path))
strcpy (posix_path, tmpbuf);
}
#endif
goto out;
}
@ -782,7 +595,8 @@ mount_info::set_flags_from_win32_path (const char *p)
for (int i = 0; i < nmounts; i++)
{
mount_item &mi = mount[native_sorted[i]];
if (path_prefix_p (mi.native_path, p, mi.native_pathlen))
if (path_prefix_p (mi.native_path, p, mi.native_pathlen,
mi.flags & MOUNT_NOPOSIX))
return mi.flags;
}
return PATH_BINARY;
@ -831,9 +645,10 @@ struct opt
{"notexec", MOUNT_NOTEXEC, 0},
{"cygexec", MOUNT_CYGWIN_EXEC, 0},
{"nosuid", 0, 0},
{"managed", MOUNT_ENC, 0},
{"acl", MOUNT_NOACL, 1},
{"noacl", MOUNT_NOACL, 0}
{"noacl", MOUNT_NOACL, 0},
{"posix=1", MOUNT_NOPOSIX, 1},
{"posix=0", MOUNT_NOPOSIX, 0}
};
static bool
@ -1196,7 +1011,7 @@ mount_info::add_item (const char *native, const char *posix,
int i;
for (i = 0; i < nmounts; i++)
{
if (strcasematch (mount[i].posix_path, posixtmp))
if (!strcmp (mount[i].posix_path, posixtmp))
{
/* Don't allow to override a system mount with a user mount. */
if ((mount[i].flags & MOUNT_SYSTEM) && !(mountflags & MOUNT_SYSTEM))
@ -1258,7 +1073,7 @@ mount_info::del_item (const char *path, unsigned flags)
{
int ent = native_sorted[i]; /* in the same order as getmntent() */
if (((posix_path_p)
? strcasematch (mount[ent].posix_path, pathtmp)
? !strcmp (mount[ent].posix_path, pathtmp)
: strcasematch (mount[ent].native_path, pathtmp)))
{
/* Don't allow to remove a system mount. */
@ -1315,7 +1130,7 @@ fillout_mntent (const char *native_path, const char *posix_path, unsigned flags)
tmp_pathbuf tp;
UNICODE_STRING unat;
tp.u_get (&unat);
get_nt_native_path (native_path, unat, flags & MOUNT_ENC);
get_nt_native_path (native_path, unat);
if (append_bs)
RtlAppendUnicodeToString (&unat, L"\\");
mntinfo.update (&unat, NULL);
@ -1352,12 +1167,13 @@ fillout_mntent (const char *native_path, const char *posix_path, unsigned flags)
strcat (_my_tls.locals.mnt_opts, (char *) ",exec");
else if (flags & MOUNT_NOTEXEC)
strcat (_my_tls.locals.mnt_opts, (char *) ",noexec");
if (flags & MOUNT_ENC)
strcat (_my_tls.locals.mnt_opts, ",managed");
if (flags & MOUNT_NOACL)
strcat (_my_tls.locals.mnt_opts, (char *) ",noacl");
if (flags & MOUNT_NOPOSIX)
strcat (_my_tls.locals.mnt_opts, (char *) ",posix=0");
if ((flags & MOUNT_CYGDRIVE)) /* cygdrive */
strcat (_my_tls.locals.mnt_opts, (char *) ",noumount");

View File

@ -71,6 +71,7 @@
#include <assert.h>
#include <ntdll.h>
#include <wchar.h>
#include <wctype.h>
bool dos_file_warning = true;
@ -84,7 +85,6 @@ struct symlink_info
int issymlink;
bool ext_tacked_on;
int error;
bool case_clash;
bool isdevice;
_major_t major;
_minor_t minor;
@ -93,7 +93,6 @@ struct symlink_info
fs_info &fs);
int set (char *path);
bool parse_device (const char *);
bool case_check (char *path);
int check_sysfile (HANDLE h);
int check_shortcut (HANDLE h);
int check_reparse_point (HANDLE h);
@ -104,8 +103,6 @@ struct symlink_info
muto NO_COPY cwdstuff::cwd_lock;
int pcheck_case = PCHECK_RELAXED; /* Determines the case check behaviour. */
static const GUID GUID_shortcut
= { 0x00021401L, 0, 0, 0xc0, 0, 0, 0, 0, 0, 0, 0x46 };
@ -154,7 +151,8 @@ struct win_shortcut_hdr
*/
int
path_prefix_p (const char *path1, const char *path2, int len1)
path_prefix_p (const char *path1, const char *path2, int len1,
bool caseinsensitive)
{
/* Handle case where PATH1 has trailing '/' and when it doesn't. */
if (len1 > 0 && isdirsep (path1[len1 - 1]))
@ -164,7 +162,8 @@ path_prefix_p (const char *path1, const char *path2, int len1)
return isdirsep (path2[0]) && !isdirsep (path2[1]);
if (isdirsep (path2[len1]) || path2[len1] == 0 || path1[len1 - 1] == ':')
return pathnmatch (path1, path2, len1);
return caseinsensitive ? strncasematch (path1, path2, len1)
: !strncmp (path1, path2, len1);
return 0;
}
@ -172,19 +171,19 @@ path_prefix_p (const char *path1, const char *path2, int len1)
/* Return non-zero if paths match in first len chars.
Check is dependent of the case sensitivity setting. */
int
pathnmatch (const char *path1, const char *path2, int len)
pathnmatch (const char *path1, const char *path2, int len, bool caseinsensitive)
{
return pcheck_case == PCHECK_STRICT ? !strncmp (path1, path2, len)
: strncasematch (path1, path2, len);
return caseinsensitive
? strncasematch (path1, path2, len) : !strncmp (path1, path2, len);
}
/* Return non-zero if paths match. Check is dependent of the case
sensitivity setting. */
int
pathmatch (const char *path1, const char *path2)
pathmatch (const char *path1, const char *path2, bool caseinsensitive)
{
return pcheck_case == PCHECK_STRICT ? !strcmp (path1, path2)
: strcasematch (path1, path2);
return caseinsensitive
? strcasematch (path1, path2) : !strcmp (path1, path2);
}
/* TODO: This function is used in mkdir and rmdir to generate correct
@ -326,9 +325,9 @@ path_conv::add_ext_from_sym (symlink_info &sym)
}
}
static void __stdcall mkrelpath (char *dst) __attribute__ ((regparm (2)));
static void __stdcall mkrelpath (char *dst, bool caseinsensitive) __attribute__ ((regparm (2)));
static void __stdcall
mkrelpath (char *path)
mkrelpath (char *path, bool caseinsensitive)
{
tmp_pathbuf tp;
char *cwd_win32 = tp.c_get ();
@ -336,7 +335,7 @@ mkrelpath (char *path)
return;
unsigned cwdlen = strlen (cwd_win32);
if (!path_prefix_p (cwd_win32, path, cwdlen))
if (!path_prefix_p (cwd_win32, path, cwdlen, caseinsensitive))
return;
size_t n = strlen (path);
@ -394,6 +393,7 @@ fs_info::update (PUNICODE_STRING upath, HANDLE in_vol)
vol = in_vol;
else
{
/* Always caseinsensitive. We really just need access to the drive. */
InitializeObjectAttributes (&attr, upath, OBJ_CASE_INSENSITIVE, NULL,
NULL);
status = NtOpenFile (&vol, READ_CONTROL, &attr, &io,
@ -523,6 +523,12 @@ fs_info::update (PUNICODE_STRING upath, HANDLE in_vol)
in fhandler.cc (fhandler_disk_file::open). */
RtlInitUnicodeString (&testname, L"SUNWNFS");
has_buggy_open (RtlEqualUnicodeString (&fsname, &testname, FALSE));
/* Case sensitivity is supported if FILE_CASE_SENSITIVE_SEARCH is set,
except on Samba which handles Windows clients case insensitive.
NFS doesn't set the FILE_CASE_SENSITIVE_SEARCH flag but is case
sensitive. */
caseinsensitive ((!(flags () & FILE_CASE_SENSITIVE_SEARCH) || is_samba ())
&& !is_nfs ());
if (!in_vol)
NtClose (vol);
@ -581,34 +587,14 @@ WCHAR tfx_chars[] NO_COPY = {
'x', 'y', 'z', '{', 0xf000 | '|', '}', '~', 127
};
WCHAR tfx_chars_managed[] NO_COPY = {
0, 1, 2, 3, 4, 5, 6, 7,
8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23,
24, 25, 26, 27, 28, 29, 30, 31,
32, '!', 0xf000 | '"', '#', '$', '%', '&', 39,
'(', ')', 0xf000 | '*', '+', ',', '-', '.', '/',
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 0xf000 | ':', ';', 0xf000 | '<', '=', 0xf000 | '>', 0xf000 | '?',
'@', 0xf000 | 'A', 0xf000 | 'B', 0xf000 | 'C', 0xf000 | 'D', 0xf000 | 'E', 0xf000 | 'F', 0xf000 | 'G',
0xf000 | 'H', 0xf000 | 'I', 0xf000 | 'J', 0xf000 | 'K', 0xf000 | 'L', 0xf000 | 'M', 0xf000 | 'N', 0xf000 | 'O',
0xf000 | 'P', 0xf000 | 'Q', 0xf000 | 'R', 0xf000 | 'S', 0xf000 | 'T', 0xf000 | 'U', 0xf000 | 'V', 0xf000 | 'W',
0xf000 | 'X', 0xf000 | 'Y', 0xf000 | '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
};
static void
transform_chars (PUNICODE_STRING upath, USHORT start_idx, bool managed)
transform_chars (PUNICODE_STRING upath, USHORT start_idx)
{
register PWCHAR buf = upath->Buffer;
register PWCHAR end = buf + upath->Length / sizeof (WCHAR) - 1;
register PWCHAR tfx = managed ? tfx_chars_managed : tfx_chars;
for (buf += start_idx; buf <= end; ++buf)
if (*buf < 128)
*buf = tfx[*buf];
*buf = tfx_chars[*buf];
#if 0
/* Win32 can't handle trailing dots and spaces. Transform the last of them
to the private use area, too, to create a valid Win32 filename. */
@ -620,7 +606,7 @@ transform_chars (PUNICODE_STRING upath, USHORT start_idx, bool managed)
}
PUNICODE_STRING
get_nt_native_path (const char *path, UNICODE_STRING& upath, bool managed)
get_nt_native_path (const char *path, UNICODE_STRING& upath)
{
upath.Length = 0;
if (path[0] == '/') /* special path w/o NT path representation. */
@ -628,9 +614,15 @@ get_nt_native_path (const char *path, UNICODE_STRING& upath, bool managed)
else if (path[0] != '\\') /* X:\... or relative path. */
{
if (path[1] == ':') /* X:\... */
str2uni_cat (upath, "\\??\\");
str2uni_cat (upath, path);
transform_chars (&upath, 7, managed);
{
str2uni_cat (upath, "\\??\\");
str2uni_cat (upath, path);
/* The drive letter must be upper case. */
upath.Buffer[4] = towupper (upath.Buffer[4]);
}
else
str2uni_cat (upath, path);
transform_chars (&upath, 7);
}
else if (path[1] != '\\') /* \Device\... */
str2uni_cat (upath, path);
@ -639,7 +631,7 @@ get_nt_native_path (const char *path, UNICODE_STRING& upath, bool managed)
{
str2uni_cat (upath, "\\??\\UNC\\");
str2uni_cat (upath, path + 2);
transform_chars (&upath, 8, managed);
transform_chars (&upath, 8);
}
else /* \\.\device or \\?\foo */
{
@ -658,7 +650,7 @@ path_conv::get_nt_native_path ()
uni_path.MaximumLength = (strlen (path) + 10) * sizeof (WCHAR);
wide_path = (PWCHAR) cmalloc_abort (HEAP_STR, uni_path.MaximumLength);
uni_path.Buffer = wide_path;
::get_nt_native_path (path, uni_path, isencoded ());
::get_nt_native_path (path, uni_path);
}
return &uni_path;
}
@ -669,7 +661,7 @@ path_conv::get_object_attr (OBJECT_ATTRIBUTES &attr, SECURITY_ATTRIBUTES &sa)
if (!get_nt_native_path ())
return NULL;
InitializeObjectAttributes (&attr, &uni_path,
OBJ_CASE_INSENSITIVE
objcaseinsensitive ()
| (sa.bInheritHandle ? OBJ_INHERIT : 0),
NULL, sa.lpSecurityDescriptor);
return &attr;
@ -708,7 +700,7 @@ warn_msdos (const char *src)
}
static DWORD
getfileattr (const char *path, bool managed) /* path has to be always absolute. */
getfileattr (const char *path, bool caseinsensitive) /* path has to be always absolute. */
{
tmp_pathbuf tp;
UNICODE_STRING upath;
@ -718,8 +710,10 @@ getfileattr (const char *path, bool managed) /* path has to be always absolute.
IO_STATUS_BLOCK io;
tp.u_get (&upath);
InitializeObjectAttributes (&attr, &upath, OBJ_CASE_INSENSITIVE, NULL, NULL);
get_nt_native_path (path, upath, managed);
InitializeObjectAttributes (&attr, &upath,
caseinsensitive ? OBJ_CASE_INSENSITIVE : 0,
NULL, NULL);
get_nt_native_path (path, upath);
status = NtQueryAttributesFile (&attr, &fbi);
if (NT_SUCCESS (status))
@ -736,7 +730,8 @@ getfileattr (const char *path, bool managed) /* path has to be always absolute.
RtlSplitUnicodePath (&upath, &dirname, &basename);
InitializeObjectAttributes (&attr, &dirname,
OBJ_CASE_INSENSITIVE, NULL, NULL);
caseinsensitive ? OBJ_CASE_INSENSITIVE : 0,
NULL, NULL);
status = NtOpenFile (&dir, SYNCHRONIZE | FILE_LIST_DIRECTORY,
&attr, &io, FILE_SHARE_VALID_FLAGS,
FILE_SYNCHRONOUS_IO_NONALERT
@ -825,10 +820,10 @@ path_conv::check (const char *src, unsigned opt,
path_flags = 0;
known_suffix = NULL;
fileattr = INVALID_FILE_ATTRIBUTES;
caseinsensitive = OBJ_CASE_INSENSITIVE;
if (wide_path)
cfree (wide_path);
wide_path = NULL;
case_clash = false;
memset (&dev, 0, sizeof (dev));
fs.clear ();
if (!normalized_path_size && normalized_path)
@ -918,7 +913,8 @@ path_conv::check (const char *src, unsigned opt,
fileattr = FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_READONLY;
else
{
fileattr = getfileattr (this->path, sym.pflags & MOUNT_ENC);
fileattr = getfileattr (this->path,
sym.pflags & MOUNT_NOPOSIX);
dev.devn = FH_FS;
}
goto out;
@ -927,7 +923,7 @@ path_conv::check (const char *src, unsigned opt,
{
dev.devn = FH_FS;
#if 0
fileattr = getfileattr (this->path, sym.pflags & MOUNT_ENC);
fileattr = getfileattr (this->path, sym.pflags & MOUNT_NOPOSIX);
if (!component && fileattr == INVALID_FILE_ATTRIBUTES)
{
fileattr = FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_READONLY;
@ -1031,81 +1027,59 @@ is_virtual_symlink:
goto out;
}
if (sym.case_clash)
if (!component)
{
if (pcheck_case == PCHECK_STRICT)
fileattr = sym.fileattr;
path_flags = sym.pflags;
if (cygwin_shared->obcaseinsensitive || fs.caseinsensitive ())
path_flags |= PATH_NOPOSIX;
caseinsensitive = (path_flags & PATH_NOPOSIX)
? OBJ_CASE_INSENSITIVE : 0;
}
/* If symlink.check found an existing non-symlink file, then
it sets the appropriate flag. It also sets any suffix found
into `ext_here'. */
if (!sym.issymlink && sym.fileattr != INVALID_FILE_ATTRIBUTES)
{
error = sym.error;
if (component == 0)
add_ext_from_sym (sym);
else if (!(sym.fileattr & FILE_ATTRIBUTE_DIRECTORY))
{
case_clash = true;
error = ENOENT;
error = ENOTDIR;
goto out;
}
/* If pcheck_case==PCHECK_ADJUST the case_clash is remembered
if the last component is concerned. This allows functions
which shall create files to avoid overriding already existing
files with another case. */
if (!component)
case_clash = true;
goto out; // file found
}
if (!(opt & PC_SYM_IGNORE))
/* Found a symlink if symlen > 0. If component == 0, then the
src path itself was a symlink. If !follow_mode then
we're done. Otherwise we have to insert the path found
into the full path that we are building and perform all of
these operations again on the newly derived path. */
else if (symlen > 0)
{
if (!component)
saw_symlinks = 1;
if (component == 0 && !need_directory && !(opt & PC_SYM_FOLLOW))
{
fileattr = sym.fileattr;
path_flags = sym.pflags;
}
/* If symlink.check found an existing non-symlink file, then
it sets the appropriate flag. It also sets any suffix found
into `ext_here'. */
if (!sym.issymlink && sym.fileattr != INVALID_FILE_ATTRIBUTES)
{
error = sym.error;
if (component == 0)
add_ext_from_sym (sym);
else if (!(sym.fileattr & FILE_ATTRIBUTE_DIRECTORY))
set_symlink (symlen); // last component of path is a symlink.
if (opt & PC_SYM_CONTENTS)
{
error = ENOTDIR;
strcpy (path, sym.contents);
goto out;
}
if (pcheck_case == PCHECK_RELAXED)
goto out; // file found
/* Avoid further symlink evaluation. Only case checks are
done now. */
opt |= PC_SYM_IGNORE;
}
/* Found a symlink if symlen > 0. If component == 0, then the
src path itself was a symlink. If !follow_mode then
we're done. Otherwise we have to insert the path found
into the full path that we are building and perform all of
these operations again on the newly derived path. */
else if (symlen > 0)
{
saw_symlinks = 1;
if (component == 0 && !need_directory && !(opt & PC_SYM_FOLLOW))
{
set_symlink (symlen); // last component of path is a symlink.
if (opt & PC_SYM_CONTENTS)
{
strcpy (path, sym.contents);
goto out;
}
add_ext_from_sym (sym);
if (pcheck_case == PCHECK_RELAXED)
goto out;
/* Avoid further symlink evaluation. Only case checks are
done now. */
opt |= PC_SYM_IGNORE;
}
else
break;
}
else if (sym.error && sym.error != ENOENT && sym.error != ENOSHARE)
{
error = sym.error;
add_ext_from_sym (sym);
goto out;
}
/* No existing file found. */
else
break;
}
else if (sym.error && sym.error != ENOENT && sym.error != ENOSHARE)
{
error = sym.error;
goto out;
}
/* No existing file found. */
virtual_component_retry:
/* Find the new "tail" of the path, e.g. in '/for/bar/baz',
@ -1246,7 +1220,7 @@ out:
if (opt & PC_NOFULL)
{
if (is_relpath)
mkrelpath (this->path);
mkrelpath (this->path, !!caseinsensitive);
if (need_directory)
{
size_t n = strlen (this->path);
@ -1587,7 +1561,7 @@ symlink_worker (const char *oldpath, const char *newpath, bool use_winsym,
if (win32_newpath.error)
{
set_errno (win32_newpath.case_clash ? ECASECLASH : win32_newpath.error);
set_errno (win32_newpath.error);
goto done;
}
@ -2334,7 +2308,8 @@ symlink_info::check (char *path, const suffix_info *suffixes, unsigned opt,
minor = 0;
mode = 0;
pflags &= ~(PATH_SYMLINK | PATH_LNK | PATH_REP);
case_clash = false;
ULONG ci_flag = cygwin_shared->obcaseinsensitive || (pflags & PATH_NOPOSIX)
? OBJ_CASE_INSENSITIVE : 0;
/* TODO: Temporarily do all char->UNICODE conversion here. This should
already be slightly faster than using Ascii functions. */
@ -2342,7 +2317,7 @@ symlink_info::check (char *path, const suffix_info *suffixes, unsigned opt,
UNICODE_STRING upath;
OBJECT_ATTRIBUTES attr;
tp.u_get (&upath);
InitializeObjectAttributes (&attr, &upath, OBJ_CASE_INSENSITIVE, NULL, NULL);
InitializeObjectAttributes (&attr, &upath, ci_flag, NULL, NULL);
PVOID eabuf = &nfs_aol_ffei;
ULONG easize = sizeof nfs_aol_ffei;
@ -2355,7 +2330,7 @@ symlink_info::check (char *path, const suffix_info *suffixes, unsigned opt,
bool no_ea = false;
error = 0;
get_nt_native_path (suffix.path, upath, pflags & MOUNT_ENC);
get_nt_native_path (suffix.path, upath);
if (h)
{
NtClose (h);
@ -2434,8 +2409,8 @@ symlink_info::check (char *path, const suffix_info *suffixes, unsigned opt,
} fdi_buf;
RtlSplitUnicodePath (&upath, &dirname, &basename);
InitializeObjectAttributes (&dattr, &dirname,
OBJ_CASE_INSENSITIVE, NULL, NULL);
InitializeObjectAttributes (&dattr, &dirname, ci_flag,
NULL, NULL);
status = NtOpenFile (&dir, SYNCHRONIZE | FILE_LIST_DIRECTORY,
&dattr, &io, FILE_SHARE_VALID_FLAGS,
FILE_SYNCHRONOUS_IO_NONALERT
@ -2475,10 +2450,6 @@ symlink_info::check (char *path, const suffix_info *suffixes, unsigned opt,
ext_tacked_on = !!*ext_here;
if (pcheck_case != PCHECK_RELAXED && !case_check (path)
|| (opt & PC_SYM_IGNORE))
goto file_not_symlink;
res = -1;
/* Windows shortcuts are potentially treated as symlinks. Valid Cygwin
@ -2569,54 +2540,12 @@ symlink_info::set (char *path)
error = 0;
issymlink = true;
isdevice = false;
ext_tacked_on = case_clash = false;
ext_tacked_on = false;
ext_here = NULL;
extn = major = minor = mode = 0;
return strlen (path);
}
/* Check the correct case of the last path component (given in DOS style).
Adjust the case in this->path if pcheck_case == PCHECK_ADJUST or return
false if pcheck_case == PCHECK_STRICT.
Dont't call if pcheck_case == PCHECK_RELAXED.
*/
bool
symlink_info::case_check (char *path)
{
WIN32_FIND_DATA data;
HANDLE h;
char *c;
/* Set a pointer to the beginning of the last component. */
if (!(c = strrchr (path, '\\')))
c = path;
else
++c;
if ((h = FindFirstFile (path, &data))
!= INVALID_HANDLE_VALUE)
{
FindClose (h);
/* If that part of the component exists, check the case. */
if (strncmp (c, data.cFileName, strlen (data.cFileName)))
{
case_clash = true;
/* If check is set to STRICT, a wrong case results
in returning a ENOENT. */
if (pcheck_case == PCHECK_STRICT)
return false;
/* PCHECK_ADJUST adjusts the case in the incoming
path which points to the path in *this. */
strcpy (c, data.cFileName);
}
}
return true;
}
/* readlink system call */
extern "C" ssize_t
@ -3267,6 +3196,7 @@ cwdstuff::set (PUNICODE_STRING nat_cwd, const char *posix_cwd, bool doit)
phdl = &get_user_proc_parms ()->CurrentDirectoryHandle;
if (!nat_cwd) /* On init, just reopen CWD with desired access flags. */
RtlInitUnicodeString (&upath, L"");
/* This is for Win32 apps only. No case sensitivity here... */
InitializeObjectAttributes (&attr, &upath,
OBJ_CASE_INSENSITIVE | OBJ_INHERIT,
nat_cwd ? NULL : *phdl, NULL);
@ -3461,7 +3391,7 @@ OBJECT_ATTRIBUTES etc::fn[MAX_ETC_FILES + 1];
LARGE_INTEGER etc::last_modified[MAX_ETC_FILES + 1];
int
etc::init (int n, PUNICODE_STRING etc_fn)
etc::init (int n, path_conv &pc)
{
if (n > 0)
/* ok */;
@ -3470,7 +3400,7 @@ etc::init (int n, PUNICODE_STRING etc_fn)
else
api_fatal ("internal error");
InitializeObjectAttributes (&fn[n], etc_fn, OBJ_CASE_INSENSITIVE, NULL, NULL);
pc.get_object_attr (fn[n], sec_none_nih);
change_possible[n] = false;
test_file_change (n);
paranoid_printf ("fn[%d] %S, curr_ix %d", n, fn[n].ObjectName, curr_ix);

View File

@ -49,7 +49,6 @@ enum pathconv_arg
{
PC_SYM_FOLLOW = 0x0001,
PC_SYM_NOFOLLOW = 0x0002,
PC_SYM_IGNORE = 0x0004,
PC_SYM_CONTENTS = 0x0008,
PC_NOFULL = 0x0010,
PC_NULLEMPTY = 0x0020,
@ -59,13 +58,6 @@ enum pathconv_arg
PC_NO_ACCESS_CHECK = 0x00800000
};
enum case_checking
{
PCHECK_RELAXED = 0,
PCHECK_ADJUST = 1,
PCHECK_STRICT = 2
};
#define PC_NONULLEMPTY -1
#include "sys/mount.h"
@ -78,9 +70,9 @@ enum path_types
PATH_EXEC = MOUNT_EXEC,
PATH_NOTEXEC = MOUNT_NOTEXEC,
PATH_CYGWIN_EXEC = MOUNT_CYGWIN_EXEC,
PATH_ENC = MOUNT_ENC,
PATH_RO = MOUNT_RO,
PATH_NOACL = MOUNT_NOACL,
PATH_NOPOSIX = MOUNT_NOPOSIX,
PATH_ALL_EXEC = (PATH_CYGWIN_EXEC | PATH_EXEC),
PATH_NO_ACCESS_CHECK = PC_NO_ACCESS_CHECK,
PATH_LNK = 0x01000000,
@ -103,6 +95,7 @@ struct fs_info
unsigned has_buggy_open : 1;
unsigned has_acls : 1;
unsigned hasgood_inode : 1;
unsigned caseinsensitive : 1;
unsigned is_fat : 1;
unsigned is_ntfs : 1;
unsigned is_samba : 1;
@ -122,6 +115,7 @@ struct fs_info
IMPLEMENT_STATUS_FLAG (bool, has_buggy_open)
IMPLEMENT_STATUS_FLAG (bool, has_acls)
IMPLEMENT_STATUS_FLAG (bool, hasgood_inode)
IMPLEMENT_STATUS_FLAG (bool, caseinsensitive)
IMPLEMENT_STATUS_FLAG (bool, is_fat)
IMPLEMENT_STATUS_FLAG (bool, is_ntfs)
IMPLEMENT_STATUS_FLAG (bool, is_samba)
@ -136,6 +130,7 @@ struct fs_info
class path_conv
{
DWORD fileattr;
ULONG caseinsensitive;
fs_info fs;
PWCHAR wide_path;
UNICODE_STRING uni_path;
@ -146,15 +141,14 @@ class path_conv
char *known_suffix;
int error;
device dev;
bool case_clash;
bool isremote () const {return fs.is_remote_drive ();}
ULONG objcaseinsensitive () const {return caseinsensitive;}
bool has_acls () const {return !(path_flags & PATH_NOACL) && fs.has_acls (); }
bool hasgood_inode () const {return fs.hasgood_inode (); }
bool isgood_inode (__ino64_t ino) const;
int has_symlinks () const {return path_flags & PATH_HAS_SYMLINKS;}
int has_buggy_open () const {return fs.has_buggy_open ();}
bool isencoded () const {return path_flags & PATH_ENC;}
int binmode () const
{
if (path_flags & PATH_BINARY)
@ -333,18 +327,17 @@ has_exec_chars (const char *buf, int len)
(buf[0] == 'M' && buf[1] == 'Z'));
}
int pathmatch (const char *path1, const char *path2) __attribute__ ((regparm (2)));
int pathnmatch (const char *path1, const char *path2, int len) __attribute__ ((regparm (2)));
int pathmatch (const char *path1, const char *path2, bool caseinsensitive) __attribute__ ((regparm (3)));
int pathnmatch (const char *path1, const char *path2, int len, bool caseinsensitive) __attribute__ ((regparm (3)));
bool has_dot_last_component (const char *dir, bool test_dot_dot) __attribute__ ((regparm (2)));
bool fnunmunge (char *, const char *) __attribute__ ((regparm (2)));
int path_prefix_p (const char *path1, const char *path2, int len1) __attribute__ ((regparm (3)));
int path_prefix_p (const char *path1, const char *path2, int len1,
bool caseinsensitive) __attribute__ ((regparm (3)));
bool is_floppy (const char *);
int normalize_win32_path (const char *, char *, char *&);
int normalize_posix_path (const char *, char *, char *&);
PUNICODE_STRING get_nt_native_path (const char *, UNICODE_STRING&, bool);
PUNICODE_STRING get_nt_native_path (const char *, UNICODE_STRING&);
/* FIXME: Move to own include file eventually */
@ -358,7 +351,7 @@ class etc
static OBJECT_ATTRIBUTES fn[MAX_ETC_FILES + 1];
static LARGE_INTEGER last_modified[MAX_ETC_FILES + 1];
static bool dir_changed (int);
static int init (int, PUNICODE_STRING);
static int init (int, path_conv &pc);
static bool file_changed (int);
static bool test_file_change (int);
friend class pwdgrp;

View File

@ -240,6 +240,25 @@ user_shared_initialize (bool reinit)
}
}
/* Initialize obcaseinsensitive. Default to case insensitive on pre-XP. */
void
shared_info::init_obcaseinsensitive ()
{
HKEY key;
DWORD size = sizeof (DWORD);
obcaseinsensitive = 1;
if (RegOpenKeyEx (HKEY_LOCAL_MACHINE,
"SYSTEM\\CurrentControlSet\\Control\\Session Manager\\kernel",
0, KEY_READ, &key) == ERROR_SUCCESS)
{
RegQueryValueEx (key, "obcaseinsensitive", NULL, NULL,
(LPBYTE) &obcaseinsensitive, &size);
RegCloseKey (key);
}
debug_printf ("obcaseinsensitive set to %d", obcaseinsensitive);
}
void
shared_info::initialize ()
{
@ -260,8 +279,10 @@ shared_info::initialize ()
if (!sversion)
{
tty.init (); /* Initialize tty table. */
mt.initialize (); /* Initialize shared tape information. */
init_obcaseinsensitive ();/* Initialize obcaseinsensitive. */
cb = sizeof (*this); /* Do last, after all shared memory initialization */
}

View File

@ -33,7 +33,6 @@ class mount_item
void init (const char *dev, const char *path, unsigned flags);
struct mntent *getmntent ();
int fnmunge (char *, const char *, int&);
int build_win32 (char *, const char *, unsigned *, unsigned);
};
@ -120,7 +119,7 @@ public:
#define SHARED_INFO_CB 31136
#define CURR_SHARED_MAGIC 0xace17c0fU
#define CURR_SHARED_MAGIC 0x18da899eU
/* NOTE: Do not make gratuitous changes to the names or organization of the
below class. The layout is checksummed to determine compatibility between
@ -136,10 +135,11 @@ class shared_info
DWORD sys_mount_table_counter;
tty_list tty;
LONG last_used_bindresvport;
DWORD obcaseinsensitivity;
DWORD obcaseinsensitive;
mtinfo mt;
void initialize ();
void init_obcaseinsensitive ();
unsigned heap_chunk_size ();
unsigned heap_slop_size ();
};

View File

@ -197,7 +197,7 @@ try_to_bin (path_conv &win32_path, HANDLE h)
RtlSplitUnicodePath (win32_path.get_nt_native_path (), &root, NULL);
root.Length -= fname.Length - sizeof (WCHAR);
/* Open root directory. */
/* Open root directory. All recycler bin ops are caseinsensitive. */
InitializeObjectAttributes (&attr, &root, OBJ_CASE_INSENSITIVE, NULL, NULL);
status = NtOpenFile (&rootdir, FILE_TRAVERSE, &attr, &io,
FILE_SHARE_VALID_FLAGS, FILE_OPEN_FOR_BACKUP_INTENT);
@ -1602,13 +1602,13 @@ rename (const char *oldpath, const char *newpath)
/* This test is necessary in almost every case, so just do it once here. */
equal_path = RtlEqualUnicodeString (oldpc.get_nt_native_path (),
newpc.get_nt_native_path (),
TRUE);
oldpc.objcaseinsensitive ());
/* First check if oldpath and newpath only differ by case. If so, it's
just a request to change the case of the filename. By simply setting
the file attributes to INVALID_FILE_ATTRIBUTES (which translates to
"file doesn't exist"), all later tests are skipped. */
if (newpc.exists () && equal_path)
if (oldpc.objcaseinsensitive () && newpc.exists () && equal_path)
{
if (RtlEqualUnicodeString (oldpc.get_nt_native_path (),
newpc.get_nt_native_path (),
@ -1646,7 +1646,7 @@ rename (const char *oldpath, const char *newpath)
newpc.check (newpath, PC_SYM_NOFOLLOW);
if (RtlEqualUnicodeString (oldpc.get_nt_native_path (),
newpc.get_nt_native_path (),
TRUE))
oldpc.objcaseinsensitive ()))
{
res = 0;
goto out;
@ -1674,7 +1674,7 @@ rename (const char *oldpath, const char *newpath)
newpc.check (newpath, PC_SYM_NOFOLLOW);
if (RtlEqualUnicodeString (oldpc.get_nt_native_path (),
newpc.get_nt_native_path (),
TRUE))
oldpc.objcaseinsensitive ()))
{
res = 0;
goto out;
@ -2776,7 +2776,8 @@ chroot (const char *newroot)
else
{
getwinenv("PATH="); /* Save the native PATH */
cygheap->root.set (path.normalized_path, path.get_win32 ());
cygheap->root.set (path.normalized_path, path.get_win32 (),
!!path.objcaseinsensitive ());
ret = 0;
}

View File

@ -495,7 +495,7 @@ utimens_worker (path_conv &win32, const struct timespec *tvp)
if (cfd->get_access () & (FILE_WRITE_ATTRIBUTES | GENERIC_WRITE)
&& RtlEqualUnicodeString (cfd->pc.get_nt_native_path (),
win32.get_nt_native_path (),
TRUE))
cfd->pc.objcaseinsensitive ()))
{
fh = cfd;
fromfd = true;

View File

@ -527,7 +527,7 @@ pwdgrp::load (const char *posix_fname)
curr_lines = 0;
pc.check (posix_fname);
etc_ix = etc::init (etc_ix, pc.get_nt_native_path ());
etc_ix = etc::init (etc_ix, pc);
paranoid_printf ("%s", posix_fname);