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-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.
}
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')
{
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 ()
unsigned posix_pathlen;
char native_path[CYG_MAX_PATH];
unsigned native_pathlen;
+ bool caseinsensitive;
};
/* CGF: FIXME This doesn't belong here */
{
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)
{
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; }
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 ());
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
}
}
-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)
{
} 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}}},
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;
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;
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;
RtlInitCountedUnicodeString (&fname, pfdi->FileName,
pfdi->FileNameLength);
InitializeObjectAttributes (&attr, &fname,
- OBJ_CASE_INSENSITIVE, fh, NULL);
+ objcaseinsensitive (), fh, NULL);
if (is_volume_mountpoint (&attr))
++count;
}
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,
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;
}
}
char new_buf[strlen (newpath) + 5];
- if (!newpc.error && !newpc.case_clash)
+ if (!newpc.error)
{
if (allow_winsymlinks && pc.is_lnk_special ())
{
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)
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,
}
}
-#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;
{
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,
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,
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];
}
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;
{
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;
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)
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 ())
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)
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)
{
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)
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;
NULL, NULL))
|| (error == ERROR_MORE_DATA))
{
- if (pathmatch (buf, file))
+ if (strcasematch (buf, file))
{
file_type = 1;
goto out;
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;
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))
{
set_io_handle (handle);
- if (pathmatch (file, DEFAULT_VALUE_NAME))
+ if (strcasematch (file, DEFAULT_VALUE_NAME))
value_name = cstrdup ("");
else
value_name = cstrdup (file);
(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;
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;
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);
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,
/* 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]) && \
!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 //?/
}
}
-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)
{
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;
}
continue;
}
- if (path_prefix_p (path, src_path, len))
+ if (path_prefix_p (path, src_path, len, mi->flags & MOUNT_NOPOSIX))
break;
}
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))
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;
}
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;
{"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
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))
{
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. */
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);
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");
#include <assert.h>
#include <ntdll.h>
#include <wchar.h>
+#include <wctype.h>
bool dos_file_warning = true;
int issymlink;
bool ext_tacked_on;
int error;
- bool case_clash;
bool isdevice;
_major_t major;
_minor_t minor;
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);
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 };
*/
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]))
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;
}
/* 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
}
}
-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 ();
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);
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,
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);
'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. */
}
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. */
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);
{
str2uni_cat (upath, "\\??\\UNC\\");
str2uni_cat (upath, path + 2);
- transform_chars (&upath, 8, managed);
+ transform_chars (&upath, 8);
}
else /* \\.\device or \\?\foo */
{
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;
}
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;
}
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;
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))
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
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)
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;
{
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;
goto out;
}
- if (sym.case_clash)
+ if (!component)
+ {
+ 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)
{
- if (pcheck_case == PCHECK_STRICT)
+ 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',
if (opt & PC_NOFULL)
{
if (is_relpath)
- mkrelpath (this->path);
+ mkrelpath (this->path, !!caseinsensitive);
if (need_directory)
{
size_t n = strlen (this->path);
if (win32_newpath.error)
{
- set_errno (win32_newpath.case_clash ? ECASECLASH : win32_newpath.error);
+ set_errno (win32_newpath.error);
goto done;
}
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. */
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;
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);
} 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
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
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
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);
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 */;
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);
{
PC_SYM_FOLLOW = 0x0001,
PC_SYM_NOFOLLOW = 0x0002,
- PC_SYM_IGNORE = 0x0004,
PC_SYM_CONTENTS = 0x0008,
PC_NOFULL = 0x0010,
PC_NULLEMPTY = 0x0020,
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"
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,
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;
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)
class path_conv
{
DWORD fileattr;
+ ULONG caseinsensitive;
fs_info fs;
PWCHAR wide_path;
UNICODE_STRING uni_path;
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)
(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 */
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;
}
}
+/* 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 ()
{
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 */
}
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);
};
#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
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 ();
};
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);
/* 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 (),
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;
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;
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;
}
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;
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);