4
0
mirror of git://sourceware.org/git/newlib-cygwin.git synced 2025-02-19 07:22:14 +08:00

* dir.cc (mkdir): Check for case clash.

* environ.cc: Add extern declaration for `pcheck_case'.
        (check_case_init): New function.
        (struct parse_thing): Add "check_case" option.
        * errno.cc (_sys_nerrlist): Add text for ECASECLASH.
        (strerror): Add case branch for ECASECLASH.
        * fhandler.cc (fhandler_disk_file::open): Check for case clash.
        * path.cc: Add global variable `pcheck_case'.
        (struct symlink_info): Add member `case_clash' and method `case_check'.
        (path_prefix_p_): Call `pathnmatch' instead of `strncasematch'.
        (pathnmatch): New funtion.
        (pathmatch): Ditto.
        (path_conv::check): Add handling for case checking.
        (symlink): Check for case clash.
        (symlink_info::check): Add parameter for case checking.
        Handle case checking.
        (symlink_info::case_check): New method.
        (chdir): Don't use unconverted path if pcheck_case==PCHECK_STRICT.
        * path.h: Add extern declarations for `pathmatch' and
        `pathnmatch'.
        (enum case_checking): New enumeration type describing
        the case checking behaviour of path conversion routines.
        (class path_conv): Add member `case_clash'.
        * syscalls.cc (_link): Check for case clash.
This commit is contained in:
Corinna Vinschen 2001-04-12 21:21:37 +00:00
parent b8a8c59d33
commit 70c370d674
8 changed files with 232 additions and 49 deletions

View File

@ -1,3 +1,30 @@
Thu Apr 17 23:19:00 2001 Corinna Vinschen <corinna@vinschen.de>
* dir.cc (mkdir): Check for case clash.
* environ.cc: Add extern declaration for `pcheck_case'.
(check_case_init): New function.
(struct parse_thing): Add "check_case" option.
* errno.cc (_sys_nerrlist): Add text for ECASECLASH.
(strerror): Add case branch for ECASECLASH.
* fhandler.cc (fhandler_disk_file::open): Check for case clash.
* path.cc: Add global variable `pcheck_case'.
(struct symlink_info): Add member `case_clash' and method `case_check'.
(path_prefix_p_): Call `pathnmatch' instead of `strncasematch'.
(pathnmatch): New funtion.
(pathmatch): Ditto.
(path_conv::check): Add handling for case checking.
(symlink): Check for case clash.
(symlink_info::check): Add parameter for case checking.
Handle case checking.
(symlink_info::case_check): New method.
(chdir): Don't use unconverted path if pcheck_case==PCHECK_STRICT.
* path.h: Add extern declarations for `pathmatch' and
`pathnmatch'.
(enum case_checking): New enumeration type describing
the case checking behaviour of path conversion routines.
(class path_conv): Add member `case_clash'.
* syscalls.cc (_link): Check for case clash.
Thu Apr 12 12:49:53 2001 Christopher Faylor <cgf@cygnus.com>
* syscalls.cc (mkfifo): New function stub.

View File

@ -306,7 +306,7 @@ mkdir (const char *dir, mode_t mode)
if (real_dir.error)
{
set_errno (real_dir.error);
set_errno (real_dir.case_clash ? ECASECLASH : real_dir.error);
goto done;
}

View File

@ -32,6 +32,7 @@ extern BOOL allow_ntea;
extern BOOL allow_smbntsec;
extern BOOL allow_winsymlinks;
extern BOOL strip_title_path;
extern int pcheck_case;
extern DWORD chunksize;
BOOL reset_com = TRUE;
static BOOL envcache = TRUE;
@ -393,6 +394,33 @@ glob_init (const char *buf)
}
}
static void
check_case_init (const char *buf)
{
if (!buf || !*buf)
return;
if (strncmp (buf, "relax", 5)== 0)
{
pcheck_case = PCHECK_RELAXED;
debug_printf ("File case checking set to RELAXED");
}
else if (strcmp (buf, "adjust")== 0)
{
pcheck_case = PCHECK_ADJUST;
debug_printf ("File case checking set to ADJUST");
}
else if (strcmp (buf, "strict")== 0)
{
pcheck_case = PCHECK_STRICT;
debug_printf ("File case checking set to STRICT");
}
else
{
debug_printf ("Wrong case checking name: %s", buf);
}
}
static void
codepage_init (const char *buf)
{
@ -441,6 +469,7 @@ struct parse_thing
} known[] =
{
{"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}}},
{"envcache", {&envcache}, justset, NULL, {{TRUE}, {FALSE}}},
{"error_start", {func: &error_start_init}, isfunc, NULL, {{0}, {0}}},

View File

@ -283,7 +283,8 @@ extern const char __declspec(dllexport) * const _sys_errlist[]=
/* ESTALE 133 */ "Stale NFS file handle",
/* ENOTSUP 134 */ "134",
/* ENOMEDIUM 135 */ "no medium",
/* ENOSHARE 136 */ "No such host or network path"
/* ENOSHARE 136 */ "No such host or network path",
/* ECASECLASH 137 */ "Filename exists with different case"
};
int __declspec(dllexport) _sys_nerr =
@ -659,6 +660,9 @@ strerror (int errnum)
case ENOSHARE:
error = "No such host or network path";
break;
case ECASECLASH:
error = "Filename exists with different case";
break;
default:
#ifdef _MT_SAFE
char *buf= _reent_winsup()->_strerror_buf;

View File

@ -1208,9 +1208,11 @@ fhandler_disk_file::open (const char *path, int flags, mode_t mode)
PC_SYM_NOFOLLOW : PC_SYM_FOLLOW);
if (real_path.error &&
(flags & O_NOSYMLINK || real_path.error != ENOENT || !(flags & O_CREAT)))
(flags & O_NOSYMLINK || real_path.error != ENOENT
|| !(flags & O_CREAT) || real_path.case_clash))
{
set_errno (real_path.error);
set_errno (flags & O_CREAT && real_path.case_clash ? ECASECLASH
: real_path.error);
syscall_printf ("0 = fhandler_disk_file::open (%s, %p)", path, flags);
return 0;
}

View File

@ -101,12 +101,17 @@ struct symlink_info
int is_symlink;
bool ext_tacked_on;
int error;
BOOL case_clash;
symlink_info (): contents (buf + MAX_PATH + 1) {}
int check (const char *path, const suffix_info *suffixes);
int check (const char *path, const suffix_info *suffixes,
char *orig_path, BOOL sym_ignore);
BOOL case_check (const char *path, char *orig_path);
};
cwdstuff cygcwd; /* The current working directory. */
int pcheck_case = PCHECK_RELAXED; /* Determines the case check behaviour. */
#define path_prefix_p(p1, p2, l1) \
((cyg_tolower(*(p1))==cyg_tolower(*(p2))) && \
path_prefix_p_(p1, p2, l1))
@ -150,12 +155,30 @@ path_prefix_p_ (const char *path1, const char *path2, int len1)
if (len1 == 0)
return SLASH_P (path2[0]) && !SLASH_P (path2[1]);
if (!strncasematch (path1, path2, len1))
if (!pathnmatch (path1, path2, len1))
return 0;
return SLASH_P (path2[len1]) || path2[len1] == 0 || path1[len1 - 1] == ':';
}
/* 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)
{
return pcheck_case == PCHECK_STRICT ? !strncmp (path1, path2, len)
: strncasematch (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)
{
return pcheck_case == PCHECK_STRICT ? !strcmp (path1, path2)
: strcasematch (path1, path2);
}
/* Convert an arbitrary path SRC to a pure Win32 path, suitable for
passing to Win32 API routines.
@ -211,6 +234,7 @@ path_conv::check (const char *src, unsigned opt,
path_flags = 0;
known_suffix = NULL;
fileattr = (DWORD) -1;
case_clash = FALSE;
for (;;)
{
MALLOC_CHECK;
@ -247,7 +271,7 @@ path_conv::check (const char *src, unsigned opt,
if (full_path[0] && full_path[1] == ':' && full_path[2] == '\0')
strcat (full_path, "\\");
if (opt & PC_SYM_IGNORE)
if ((opt & PC_SYM_IGNORE) && pcheck_case == PCHECK_RELAXED)
{
fileattr = GetFileAttributesA (path);
goto out;
@ -284,8 +308,17 @@ path_conv::check (const char *src, unsigned opt,
sym.pflags = path_flags;
}
int len = sym.check (path_copy, suff);
int len = sym.check (path_copy, suff, full_path, opt & PC_SYM_IGNORE);
if (sym.case_clash)
{
case_clash = TRUE;
error = ENOENT;
goto out;
}
if (!(opt & PC_SYM_IGNORE))
{
if (!component)
path_flags = sym.pflags;
@ -298,9 +331,18 @@ path_conv::check (const char *src, unsigned opt,
if (component == 0)
{
fileattr = sym.fileattr;
goto fillin;
if (sym.ext_here && *sym.ext_here)
{
known_suffix = this->path + sym.extn;
if (sym.ext_tacked_on)
strcpy (known_suffix, sym.ext_here);
}
}
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 len > 0. If component == 0, then the
src path itself was a symlink. If !follow_mode then
@ -315,14 +357,29 @@ path_conv::check (const char *src, unsigned opt,
set_symlink (); // last component of path is a symlink.
fileattr = sym.fileattr;
if (opt & PC_SYM_CONTENTS)
{
strcpy (path, sym.contents);
goto fillin;
goto out;
}
if (sym.ext_here && *sym.ext_here)
{
known_suffix = this->path + sym.extn;
if (sym.ext_tacked_on)
strcpy (known_suffix, sym.ext_here);
}
if (pcheck_case == PCHECK_RELAXED)
goto out;
/* Avoid further symlink evaluation. Only case checks are
done now. */
opt |= PC_SYM_IGNORE;
}
else
break;
}
/* No existing file found. */
}
if (!(tail = strrchr (path_copy, '\\')) ||
(tail > path_copy && tail[-1] == ':'))
goto out; // all done
@ -378,7 +435,7 @@ path_conv::check (const char *src, unsigned opt,
}
}
fillin:
/*fillin:*/
if (sym.ext_here && *sym.ext_here && !(opt & PC_SYM_CONTENTS))
{
known_suffix = this->path + sym.extn;
@ -399,6 +456,7 @@ out:
error = ENOTDIR;
return;
}
DWORD serial, volflags;
char fs_name[16];
@ -2258,18 +2316,17 @@ symlink (const char *topath, const char *frompath)
char w32topath[MAX_PATH + 1];
DWORD written;
if (allow_winsymlinks)
win32_path.check (frompath, PC_SYM_NOFOLLOW);
if (allow_winsymlinks && !win32_path.error)
{
strcpy (from, frompath);
strcat (from, ".lnk");
win32_path.check (from, PC_SYM_NOFOLLOW);
}
else
win32_path.check (frompath, PC_SYM_NOFOLLOW);
if (win32_path.error)
{
set_errno (win32_path.error);
set_errno (win32_path.case_clash ? ECASECLASH : win32_path.error);
goto done;
}
@ -2573,7 +2630,8 @@ suffix_scan::next ()
stored into BUF if PATH is a symlink. */
int
symlink_info::check (const char *path, const suffix_info *suffixes)
symlink_info::check (const char *path, const suffix_info *suffixes,
char *orig_path, BOOL sym_ignore)
{
HANDLE h;
int res = 0;
@ -2585,6 +2643,8 @@ symlink_info::check (const char *path, const suffix_info *suffixes)
ext_tacked_on = !*ext_here;
case_clash = FALSE;
while (suffix.next ())
{
error = 0;
@ -2599,6 +2659,10 @@ symlink_info::check (const char *path, const suffix_info *suffixes)
continue;
}
if (pcheck_case != PCHECK_RELAXED && !case_check (path, orig_path)
|| sym_ignore)
goto file_not_symlink;
int sym_check = 0;
if (fileattr & FILE_ATTRIBUTE_DIRECTORY)
@ -2662,6 +2726,50 @@ out:
return res;
}
/* 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 (const char *path, char *orig_path)
{
WIN32_FIND_DATA data;
HANDLE h;
const 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 (strcmp (c, data.cFileName))
{
/* If check is set to STRICT, a wrong case results
in returning a ENOENT. */
if (pcheck_case == PCHECK_STRICT)
{
case_clash = TRUE;
return FALSE;
}
/* PCHECK_ADJUST adjusts the case in the incoming
path which points to the path in *this. */
strncpy (orig_path + (c - path), data.cFileName,
strlen (data.cFileName));
}
}
return TRUE;
}
/* readlink system call */
extern "C"
@ -2855,7 +2963,8 @@ chdir (const char *dir)
we'll see if Cygwin mailing list users whine about the current behavior. */
if (res == -1)
__seterrno ();
else if (!path.has_symlinks () && strpbrk (dir, ":\\") == NULL)
else if (!path.has_symlinks () && strpbrk (dir, ":\\") == NULL
&& pcheck_case == PCHECK_RELAXED)
cygcwd.set (path, dir);
else
cygcwd.set (path, NULL);

View File

@ -25,6 +25,13 @@ enum pathconv_arg
PC_NULLEMPTY = 0x0020
};
enum case_checking
{
PCHECK_RELAXED = 0,
PCHECK_ADJUST = 1,
PCHECK_STRICT = 2
};
#define PC_NONULLEMPTY -1
#include <sys/mount.h>
@ -89,6 +96,8 @@ class path_conv
DWORD fileattr;
BOOL case_clash;
void check (const char *src, unsigned opt = PC_SYM_FOLLOW,
const suffix_info *suffixes = NULL) __attribute__ ((regparm(3)));
@ -171,3 +180,6 @@ struct cwdstuff
};
extern cwdstuff cygcwd;
extern int pathmatch (const char *path1, const char *path2);
extern int pathnmatch (const char *path1, const char *path2, int len);

View File

@ -545,7 +545,7 @@ _link (const char *a, const char *b)
}
if (real_b.error)
{
set_errno (real_b.error);
set_errno (real_b.case_clash ? ECASECLASH : real_b.error);
goto done;
}